[haiku-commits] r36341 - in haiku/branches/developer/zooey/posix-locale: headers/private/libroot headers/private/libroot/locale headers/private/libroot/time src/system/libroot/posix/locale src/system/libroot/posix/time ...

Author: zooey
Date: 2010-04-18 22:18:40 +0200 (Sun, 18 Apr 2010)
New Revision: 36341
Changeset: http://dev.haiku-os.org/changeset/36341/haiku

Added:
   haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/
   
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/ICULocaleBackend.h
   
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/LocaleBackend.h
   
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/time/timelocal.h
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/timelocal.cpp
Removed:
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.h
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/LocaleBackend.h
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/timelocal.c
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/timelocal.h
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/Jamfile
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/Jamfile
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/strftime.c
   
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/strptime.c
   
haiku/branches/developer/zooey/posix-locale/src/tests/system/libroot/posix/locale_test.cpp
Log:
implemented support for LC-time information, as used in strftime() and 
strptime():
* fleshed out TimeData in ICULocaleBackend, which is now fetching all the
  information required to fill lc_time_t from ICU
* moved timelocal.h to headers/private/time
* moved locale-private headers to headers/private/locale
* adjusted strftime() and strptime() to make use of LocaleBackend
* added tests for LC-time info to locale_test
* adjusted codings style of class declarations to use one indent before
  the "virtual"/"static" keyword


Copied: 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/ICULocaleBackend.h
 (from rev 36176, 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.h)
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/ICULocaleBackend.h
                               (rev 0)
+++ 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/ICULocaleBackend.h
       2010-04-18 20:18:40 UTC (rev 36341)
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2010, Oliver Tappe, zooey@xxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _ICU_LOCALE_BACKEND_H
+#define _ICU_LOCALE_BACKEND_H
+
+
+#include <unicode/dcfmtsym.h>
+#include <unicode/datefmt.h>
+#include <unicode/locid.h>
+#include <unicode/ucnv.h>
+#include <unicode/unistr.h>
+
+#include "LocaleBackend.h"
+
+
+namespace BPrivate {
+
+
+typedef DecimalFormatSymbols::ENumberFormatSymbol FormatSymbol;
+
+class CategoryData {
+public:
+                                                               CategoryData();
+       virtual                                         ~CategoryData();
+
+       virtual status_t                        SetTo(const Locale& locale,
+                                                                       const 
char* posixLocaleName);
+
+                       const char *            PosixLocaleName()
+                                                                       { 
return fPosixLocaleName; }
+
+protected:
+                       status_t                        
_ConvertUnicodeStringToLocaleconvEntry(
+                                                                       const 
UnicodeString& string,
+                                                                       char* 
destination, int destinationSize,
+                                                                       char* 
defaultValue = "");
+
+       static  const uint16            skMaxPosixLocaleNameLen = 128;
+
+                       Locale                          fLocale;
+                       UConverter*                     fConverter;
+                       char                            
fPosixLocaleName[skMaxPosixLocaleNameLen];
+                       char                            
fGivenCharset[UCNV_MAX_CONVERTER_NAME_LENGTH];
+};
+
+
+class CollateData : public CategoryData {
+public:
+       virtual status_t                        SetTo(const Locale& locale,
+                                                                               
const char* posixLocaleName);
+};
+
+
+class CtypeData : public CategoryData {
+public:
+                                                               CtypeData();
+       virtual                                         ~CtypeData();
+
+       virtual status_t                        SetTo(const Locale& locale,
+                                                                       const 
char* posixLocaleName);
+
+private:
+};
+
+
+class MessagesData : public CategoryData {
+public:
+       virtual status_t                        SetTo(const Locale& locale,
+                                                                       const 
char* posixLocaleName);
+};
+
+
+class LocaleconvData : public CategoryData {
+protected:
+                       status_t                        _SetLocaleconvEntry(
+                                                                       const 
DecimalFormatSymbols* formatSymbols,
+                                                                       char* 
destination, FormatSymbol symbol,
+                                                                       char* 
defaultValue = "");
+};
+
+
+class MonetaryData : public LocaleconvData {
+public:
+       static  const int32                     
kParenthesesAroundCurrencyAndValue = 0;
+       static  const int32                     kSignPrecedesCurrencyAndValue   
   = 1;
+       static  const int32                     kSignSucceedsCurrencyAndValue   
   = 2;
+       static  const int32                     
kSignImmediatelyPrecedesCurrency   = 3;
+       static  const int32                     
kSignImmediatelySucceedsCurrency   = 4;
+
+       virtual status_t                        SetTo(const Locale& locale,
+                                                                       const 
char* posixLocaleName);
+
+private:
+       static  const int32                     kCsPrecedesFlag = 1 << 0;
+       static  const int32                     kSepBySpaceFlag = 1 << 1;
+
+                       int32                           
_DetermineCurrencyPosAndSeparator(
+                                                                       const 
UnicodeString& prefix,
+                                                                       const 
UnicodeString& suffix,
+                                                                       const 
UnicodeString& signSymbol,
+                                                                       const 
UnicodeString& currencySymbol,
+                                                                       UChar& 
currencySeparatorChar);
+                       int32                           _DetermineSignPos(const 
UnicodeString& prefix,
+                                                                       const 
UnicodeString& suffix,
+                                                                       const 
UnicodeString& signSymbol,
+                                                                       const 
UnicodeString& currencySymbol);
+};
+
+
+class NumericData : public LocaleconvData {
+public:
+       virtual status_t                        SetTo(const Locale& locale,
+                                                                       const 
char* posixLocaleName);
+};
+
+
+class TimeData : public CategoryData {
+public:
+       virtual status_t                        SetTo(const Locale& locale,
+                                                                       const 
char* posixLocaleName);
+
+private:
+                       status_t                        _SetLCTimeEntries(const 
UnicodeString* strings,
+                                                                       char* 
destination, int entrySize,
+                                                                       int 
count, int maxCount);
+                       status_t                        
_SetLCTimePattern(DateFormat* format,
+                                                                       char* 
destination, int destinationSize);
+};
+
+
+class ICULocaleBackend : public LocaleBackend {
+public:
+                                                               
ICULocaleBackend();
+       virtual                                         ~ICULocaleBackend();
+
+       virtual const char*                     SetLocale(int category,
+                                                                       const 
char* posixLocaleName);
+       virtual const struct lconv*     LocaleConv();
+       virtual const struct lc_time_t* LCTimeInfo();
+
+private:
+                       const char*                     _QueryLocale(int 
category);
+
+                       CollateData                     fCollateData;
+                       CtypeData                       fCtypeData;
+                       MessagesData            fMessagesData;
+                       MonetaryData            fMonetaryData;
+                       NumericData                     fNumericData;
+                       TimeData                        fTimeData;
+};
+
+
+}      // namespace BPrivate
+
+
+#endif // _ICU_LOCALE_BACKEND_H

Copied: 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/LocaleBackend.h
 (from rev 36014, 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/LocaleBackend.h)
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/LocaleBackend.h
                          (rev 0)
+++ 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/locale/LocaleBackend.h
  2010-04-18 20:18:40 UTC (rev 36341)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010, Oliver Tappe, zooey@xxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _LOCALE_BACKEND_H
+#define _LOCALE_BACKEND_H
+
+
+#include <SupportDefs.h>
+
+
+struct lconv;
+struct lc_time_t;
+
+
+namespace BPrivate {
+
+
+class LocaleBackend {
+public:
+                                                               LocaleBackend();
+       virtual                                         ~LocaleBackend();
+
+       virtual const char*                     SetLocale(int category, const 
char* locale) = 0;
+       virtual const struct lconv*     LocaleConv() = 0;
+       virtual const struct lc_time_t* LCTimeInfo() = 0;
+
+       static  status_t                        LoadBackend();
+};
+
+
+extern LocaleBackend* gLocaleBackend;
+
+
+}      // namespace BPrivate
+
+
+#endif // _LOCALE_BACKEND_H

Copied: 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/time/timelocal.h
 (from rev 35983, 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/timelocal.h)
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/time/timelocal.h
                                (rev 0)
+++ 
haiku/branches/developer/zooey/posix-locale/headers/private/libroot/time/timelocal.h
        2010-04-18 20:18:40 UTC (rev 36341)
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1997-2002 FreeBSD Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: /repoman/r/ncvs/src/lib/libc/stdtime/timelocal.h,v 1.11 
2002/01/24 15:07:44 phantom Exp $
+ */
+#ifndef _TIMELOCAL_H_
+#define        _TIMELOCAL_H_
+
+
+#include <sys/cdefs.h>
+
+
+/*
+ * Private header file for the strftime and strptime localization
+ * stuff.
+ */
+struct lc_time_t {
+       const char* mon[12];
+       const char* month[12];
+       const char* wday[7];
+       const char* weekday[7];
+       const char* X_fmt;
+       const char* x_fmt;
+       const char* c_fmt;
+       const char* am;
+       const char* pm;
+       const char* date_fmt;
+       const char* alt_month[12];
+       const char* md_order;
+       const char* ampm_fmt;
+};
+
+__BEGIN_DECLS
+const struct lc_time_t* __get_current_time_locale(void);
+__END_DECLS
+
+
+#endif /* !_TIMELOCAL_H_ */

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-18 17:06:02 UTC (rev 36340)
+++ 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/ICULocaleBackend.cpp
    2010-04-18 20:18:40 UTC (rev 36341)
@@ -12,7 +12,11 @@
 #include <locale.h>
 #include <string.h>
 
+#include <timelocal.h>
+
 #include <unicode/decimfmt.h>
+#include <unicode/dtfmtsym.h>
+#include <unicode/smpdtfmt.h>
 
 
 namespace BPrivate {
@@ -23,17 +27,17 @@
  * 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 const uint16 kLCBufSize = 10;
+static char sDecimalPoint[kLCBufSize] = ".";
+static char sThousandsSep[kLCBufSize] = "";
+static char sGrouping[kLCBufSize] = "";
+static char sIntCurrSymbol[kLCBufSize] = "";
+static char sCurrencySymbol[kLCBufSize] = "";
+static char sMonDecimalPoint[kLCBufSize] = "";
+static char sMonThousandsSep[kLCBufSize] = "";
+static char sMonGrouping[kLCBufSize] = "";
+static char sPositiveSign[kLCBufSize] = "";
+static char sNegativeSign[kLCBufSize] = "";
 static struct lconv sLocaleConv = {
        sDecimalPoint,
        sThousandsSep,
@@ -62,6 +66,69 @@
 };
 
 
+/*
+ * 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 char sMon[12][24] = {
+       "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+static char sMonth[12][64] = {
+       "January", "February", "March", "April", "May", "June",
+       "July", "August", "September", "October", "November", "December"
+};
+static char sWday[7][24] = {
+       "Sun", "Mon", "Tue", "Wed",     "Thu", "Fri", "Sat"
+};
+static char sWeekday[7][64] = {
+       "Sunday", "Monday", "Tuesday", "Wednesday",     "Thursday", "Friday", 
"Saturday"
+};
+static char sTimeFmt[24] = "%H:%M:%S";
+static char sDateFmt[24] = "%m/%d/%y";
+static char sDateTimeFmt[32] = "%a %b %e %H:%M:%S %Y";
+static char sAM[24] = "AM";
+static char sPM[24] = "PM";
+static char sDateTimeZoneFmt[32] = "%a %b %e %H:%M:%S %Z %Y";
+static char sAltMonth[12][64] = {
+       "January", "February", "March", "April", "May", "June",
+       "July", "August", "September", "October", "November", "December"
+};
+static char sMdOrder[4] = "md";
+static char sAmPmFmt[32] = "%I:%M:%S %p";
+static const struct lc_time_t sLCTimeInfo = {
+       {
+               sMon[0], sMon[1], sMon[2], sMon[3], sMon[4], sMon[5],
+               sMon[6], sMon[7], sMon[8], sMon[9], sMon[10], sMon[11]
+       },
+       {
+               sMonth[0], sMonth[1], sMonth[2], sMonth[3], sMonth[4], 
sMonth[5],
+               sMonth[6], sMonth[7], sMonth[8], sMonth[9], sMonth[10], 
sMonth[11]
+       },
+       {
+               sWday[0], sWday[1], sWday[2], sWday[3], sWday[4], sWday[5], 
sWday[6]
+       },
+       {
+               sWeekday[0], sWeekday[1], sWeekday[2], sWeekday[3],
+               sWeekday[4], sWeekday[5], sWeekday[6]
+       },
+       sTimeFmt,
+       sDateFmt,
+       sDateTimeFmt,
+       sAM,
+       sPM,
+       sDateTimeZoneFmt,
+       {
+               sAltMonth[0], sAltMonth[1], sAltMonth[2], sAltMonth[3],
+               sAltMonth[4], sAltMonth[5], sAltMonth[6], sAltMonth[7],
+               sAltMonth[8], sAltMonth[9], sAltMonth[10], sAltMonth[11]
+       },
+       sMdOrder,
+       sAmPmFmt
+};
+
+
 CategoryData::CategoryData()
        :
        fConverter(NULL)
@@ -121,14 +188,15 @@
 
 
 status_t
-CategoryData::_ConvertUnicodeStringToLocaleconvEntry(UnicodeString& string,
-       char* destination, char* defaultValue)
+CategoryData::_ConvertUnicodeStringToLocaleconvEntry(
+       const UnicodeString& string, char* destination, int destinationSize,
+       char* defaultValue)
 {
        status_t result = B_OK;
        UErrorCode icuStatus = U_ZERO_ERROR;
 
-       ucnv_fromUChars(fConverter, destination, skLCBufSize, 
string.getBuffer(),
-               string.length(), &icuStatus);
+       ucnv_fromUChars(fConverter, destination, destinationSize,
+               string.getBuffer(), string.length(), &icuStatus);
        if (!U_SUCCESS(icuStatus)) {
                switch (icuStatus) {
                        case U_BUFFER_OVERFLOW_ERROR:
@@ -196,7 +264,7 @@
        UnicodeString symbolString = formatSymbols->getSymbol(symbol);
        if (!symbolString.isEmpty()) {
                result = _ConvertUnicodeStringToLocaleconvEntry(symbolString,
-                       destination, defaultValue);
+                       destination, kLCBufSize, defaultValue);
        } else
                destination[0] = '\0';
 
@@ -317,7 +385,7 @@
                        if (intlCurrencySeparatorChar != CHAR_MAX)
                                intlCurrencySymbol += intlCurrencySeparatorChar;
                        result = 
_ConvertUnicodeStringToLocaleconvEntry(intlCurrencySymbol,
-                               sIntCurrSymbol);
+                               sIntCurrSymbol, kLCBufSize);
                }
                if (result == B_OK) {
                        result = _SetLocaleconvEntry(formatSymbols, 
sCurrencySymbol,
@@ -382,7 +450,7 @@
 /*
  * This method determines the <>_sign_posn value according to the following
  * map (where '$' indicated the currency symbol, '#' the number value, and
- * '-' the sign symbol [or alternatively the paranthesis]):
+ * '-' or parantheses the sign symbol):
  *             ($#)    ->      0
  *             (#$)    ->      0
  *             -$#     ->      1
@@ -399,7 +467,7 @@
 {
        if (prefix.indexOf(UnicodeString("(", "")) >= 0
                && suffix.indexOf(UnicodeString(")", "")) >= 0)
-               return 0;       // parentheses around currency and value
+               return kParenthesesAroundCurrencyAndValue;
 
        UnicodeString value("#", "");
        UnicodeString prefixNumberSuffixString = prefix + value + suffix;
@@ -410,13 +478,13 @@
                        = prefixNumberSuffixString.indexOf(currencySymbol);
 
                if (signSymbolPos < valuePos && signSymbolPos < 
currencySymbolPos)
-                       return 1;       // sign precedes currency and value
+                       return kSignPrecedesCurrencyAndValue;
                if (signSymbolPos > valuePos && signSymbolPos > 
currencySymbolPos)
-                       return 2;       // sign succeeds currency and value
+                       return kSignSucceedsCurrencyAndValue;
                if (signSymbolPos == currencySymbolPos - 1)
-                       return 3;       // sign immediately precedes currency
+                       return kSignImmediatelyPrecedesCurrency;
                if (signSymbolPos == currencySymbolPos + 
currencySymbol.length())
-                       return 4;       // sign immediately succeeds currency
+                       return kSignImmediatelySucceedsCurrency;
        }
 
        return CHAR_MAX;
@@ -478,11 +546,250 @@
 TimeData::SetTo(const Locale& locale, const char* posixLocaleName)
 {
        status_t result = CategoryData::SetTo(locale, posixLocaleName);
+       if (result != B_OK)
+               return result;
 
+       UErrorCode icuStatus = U_ZERO_ERROR;
+       DateFormatSymbols formatSymbols(fLocale, icuStatus);
+       if (!U_SUCCESS(icuStatus))
+               return B_UNSUPPORTED;
+
+       int count = 0;
+       const UnicodeString* strings = formatSymbols.getShortMonths(count);
+       result = _SetLCTimeEntries(strings, sMon[0], sizeof(sMon[0]), count, 
12);
+
+       if (result == B_OK) {
+               strings = formatSymbols.getMonths(count);
+               result = _SetLCTimeEntries(strings, sMonth[0], 
sizeof(sMonth[0]), count,
+                       12);
+       }
+
+       if (result == B_OK) {
+               strings = formatSymbols.getShortWeekdays(count);
+               if (count == 8 && strings[0].length() == 0) {
+                       // ICUs weekday arrays are 1-based
+                       strings++;
+                       count = 7;
+               }
+               result = _SetLCTimeEntries(strings, sWday[0], sizeof(sWday[0]), 
count,
+                       7);
+       }
+
+       if (result == B_OK) {
+               strings = formatSymbols.getWeekdays(count);
+               if (count == 8 && strings[0].length() == 0) {
+                       // ICUs weekday arrays are 1-based
+                       strings++;
+                       count = 7;
+               }
+               result = _SetLCTimeEntries(strings, sWeekday[0], 
sizeof(sWeekday[0]),
+                       count, 7);
+       }
+
+       if (result == B_OK) {
+               try {
+                       DateFormat* format = DateFormat::createTimeInstance(
+                               DateFormat::kDefault, fLocale);
+                       result = _SetLCTimePattern(format, sTimeFmt, 
sizeof(sTimeFmt));
+                       delete format;
+               } catch(...) {
+                       result = B_NO_MEMORY;
+               }
+       }
+
+       if (result == B_OK) {
+               try {
+                       DateFormat* format = DateFormat::createDateInstance(
+                               DateFormat::kDefault, fLocale);
+                       result = _SetLCTimePattern(format, sDateFmt, 
sizeof(sDateFmt));
+                       delete format;
+               } catch(...) {
+                       result = B_NO_MEMORY;
+               }
+       }
+
+       if (result == B_OK) {
+               try {
+                       DateFormat* format = DateFormat::createDateTimeInstance(
+                               DateFormat::kFull, DateFormat::kFull, fLocale);
+                       result = _SetLCTimePattern(format, sDateTimeFmt,
+                               sizeof(sDateTimeFmt));
+                       delete format;
+               } catch(...) {
+                       result = B_NO_MEMORY;
+               }
+       }
+
+       if (result == B_OK) {
+               strings = formatSymbols.getAmPmStrings(count);
+               result = _SetLCTimeEntries(strings, sAM, sizeof(sAM), 1, 1);
+               if (result == B_OK)
+                       result = _SetLCTimeEntries(&strings[1], sPM, 
sizeof(sPM), 1, 1);
+       }
+
+       if (result == B_OK) {
+               strings = formatSymbols.getMonths(count, 
DateFormatSymbols::STANDALONE,
+                       DateFormatSymbols::WIDE);
+               result = _SetLCTimeEntries(strings, sAltMonth[0], 
sizeof(sAltMonth[0]),
+                       count, 12);
+       }
+
        return result;
 }
 
 
+status_t
+TimeData::_SetLCTimeEntries(const UnicodeString* strings, char* destination,
+       int entrySize, int count, int maxCount)
+{
+       if (strings == NULL)
+               return B_ERROR;
+
+       status_t result = B_OK;
+       if (count > maxCount)
+               count = maxCount;
+       for (int32 i = 0; result == B_OK && i < count; ++i) {
+               result = _ConvertUnicodeStringToLocaleconvEntry(strings[i], 
destination,
+                       entrySize);
+               destination += entrySize;
+       }
+
+       return result;
+}
+
+
+status_t
+TimeData::_SetLCTimePattern(DateFormat* format, char* destination,
+       int destinationSize)
+{
+       SimpleDateFormat* simpleFormat = 
dynamic_cast<SimpleDateFormat*>(format);
+       if (!simpleFormat)
+               return B_BAD_TYPE;
+
+       // convert ICU-type pattern to posix (i.e. strftime()) format string
+       UnicodeString icuPattern;
+       simpleFormat->toPattern(icuPattern);
+       UnicodeString posixPattern;
+       if (icuPattern.length() > 0) {
+               UChar lastCharSeen = 0;
+               int lastCharCount = 1;
+               bool inSingleQuotes = false;
+               bool inDoubleQuotes = false;
+               // we loop one character past the end on purpose, which will 
result in a
+               // final -1 char to be processed, which in turn will let us 
handle the
+               // last character (via lastCharSeen)
+               for (int i = 0; i <= icuPattern.length(); ++i) {
+                       UChar currChar = icuPattern.charAt(i);
+                       if (lastCharSeen != 0 && currChar == lastCharSeen) {
+                               lastCharCount++;
+                               continue;
+                       }
+
+                       if (!inSingleQuotes && !inDoubleQuotes) {
+                               switch (lastCharSeen) {
+                                       case L'a':
+                                               
posixPattern.append(UnicodeString("%p", ""));
+                                               break;
+                                       case L'd':
+                                               if (lastCharCount == 2)
+                                                       
posixPattern.append(UnicodeString("%d", ""));
+                                               else
+                                                       
posixPattern.append(UnicodeString("%e", ""));
+                                               break;
+                                       case L'D':
+                                               
posixPattern.append(UnicodeString("%j", ""));
+                                               break;
+                                       case L'c':
+                                               // fall through, to handle 'c' 
the same as 'e'
+                                       case L'e':
+                                               if (lastCharCount == 4)
+                                                       
posixPattern.append(UnicodeString("%A", ""));
+                                               else if (lastCharCount <= 2)
+                                                       
posixPattern.append(UnicodeString("%u", ""));
+                                               else
+                                                       
posixPattern.append(UnicodeString("%a", ""));
+                                               break;
+                                       case L'E':
+                                               if (lastCharCount == 4)
+                                                       
posixPattern.append(UnicodeString("%A", ""));
+                                               else
+                                                       
posixPattern.append(UnicodeString("%a", ""));
+                                               break;
+                                       case L'k':
+                                               // fall through, to handle 'k' 
the same as 'h'
+                                       case L'h':
+                                               if (lastCharCount == 2)
+                                                       
posixPattern.append(UnicodeString("%I", ""));
+                                               else
+                                                       
posixPattern.append(UnicodeString("%l", ""));
+                                               break;
+                                       case L'H':
+                                               if (lastCharCount == 2)
+                                                       
posixPattern.append(UnicodeString("%H", ""));
+                                               else
+                                                       
posixPattern.append(UnicodeString("%k", ""));
+                                               break;
+                                       case L'm':
+                                               
posixPattern.append(UnicodeString("%M", ""));
+                                               break;
+                                       case L'L':
+                                               // fall through, to handle 'L' 
the same as 'M'
+                                       case L'M':
+                                               if (lastCharCount == 4)
+                                                       
posixPattern.append(UnicodeString("%B", ""));
+                                               else if (lastCharCount == 3)
+                                                       
posixPattern.append(UnicodeString("%b", ""));
+                                               else
+                                                       
posixPattern.append(UnicodeString("%m", ""));
+                                               break;
+                                       case L's':
+                                               
posixPattern.append(UnicodeString("%S", ""));
+                                               break;
+                                       case L'w':
+                                               
posixPattern.append(UnicodeString("%V", ""));
+                                               break;
+                                       case L'y':
+                                               if (lastCharCount == 2)
+                                                       
posixPattern.append(UnicodeString("%y", ""));
+                                               else
+                                                       
posixPattern.append(UnicodeString("%Y", ""));
+                                               break;
+                                       case L'Y':
+                                               
posixPattern.append(UnicodeString("%G", ""));
+                                               break;
+                                       case L'z':
+                                               
posixPattern.append(UnicodeString("%Z", ""));
+                                               break;
+                                       case L'Z':
+                                               
posixPattern.append(UnicodeString("%z", ""));
+                                               break;
+                                       default:
+                                               if (lastCharSeen != 0)
+                                                       
posixPattern.append(lastCharSeen);
+                               }
+                       } else {
+                               if (lastCharSeen != 0)
+                                       posixPattern.append(lastCharSeen);
+                       }
+
+                       if (currChar == L'"') {
+                               inDoubleQuotes = !inDoubleQuotes;
+                               lastCharSeen = 0;
+                       } else if (currChar == L'\'') {
+                               inSingleQuotes = !inSingleQuotes;
+                               lastCharSeen = 0;
+                       } else
+                               lastCharSeen = currChar;
+
+                       lastCharCount = 1;
+               }
+       }
+
+       return _ConvertUnicodeStringToLocaleconvEntry(posixPattern, destination,
+               destinationSize);
+}
+
+
 extern "C" LocaleBackend*
 CreateInstance()
 {
@@ -550,13 +857,20 @@
 }
 
 
-struct lconv*
+const struct lconv*
 ICULocaleBackend::LocaleConv()
 {
        return &sLocaleConv;
 }
 
 
+const struct lc_time_t*
+ICULocaleBackend::LCTimeInfo()
+{
+       return &sLCTimeInfo;
+}
+
+
 const char*
 ICULocaleBackend::_QueryLocale(int category)
 {

Modified: 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/Jamfile
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/Jamfile
 2010-04-18 17:06:02 UTC (rev 36340)
+++ 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/locale/Jamfile
 2010-04-18 20:18:40 UTC (rev 36341)
@@ -13,6 +13,8 @@
 ;
 
 UseLibraryHeaders icu ;
+UsePrivateHeaders [ FDirName libroot locale ] ;
+UsePrivateHeaders [ FDirName libroot time ] ;
 
 SharedLibrary libroot-addon-locale.so
        :

Modified: 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/Jamfile
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/Jamfile
   2010-04-18 17:06:02 UTC (rev 36340)
+++ 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/Jamfile
   2010-04-18 20:18:40 UTC (rev 36341)
@@ -4,6 +4,7 @@
 SubDirCcFlags -DNOID -DTZDIR='get_timezones_directory()' -DUSG_COMPAT
        -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DPCTS=1 -DSTD_INSPIRED ;
 
+UsePrivateHeaders [ FDirName libroot locale ] ;
 UsePrivateHeaders [ FDirName libroot time ] ;
 UsePrivateSystemHeaders ;
 
@@ -17,7 +18,7 @@
        stime.c
        strftime.c
        strptime.c
-       timelocal.c
+       timelocal.cpp
        time.c
 ;
 

Modified: 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/strftime.c
===================================================================
--- 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/strftime.c
        2010-04-18 17:06:02 UTC (rev 36340)
+++ 
haiku/branches/developer/zooey/posix-locale/src/system/libroot/posix/time/strftime.c
        2010-04-18 20:18:40 UTC (rev 36341)
@@ -36,76 +36,10 @@
 #include "tzfile.h"
 #include "fcntl.h"
 #include "locale.h"
+#include "timelocal.h"
 
-struct lc_time_T {
-       const char *    mon[MONSPERYEAR];
-       const char *    month[MONSPERYEAR];
-       const char *    wday[DAYSPERWEEK];
-       const char *    weekday[DAYSPERWEEK];
-       const char *    X_fmt;
-       const char *    x_fmt;
-       const char *    c_fmt;
-       const char *    am;
-       const char *    pm;
-       const char *    date_fmt;
-};
+#define Locale __get_current_time_locale()
 
-#ifdef LOCALE_HOME
-#include "sys/stat.h"
-static struct lc_time_T                localebuf;
-static struct lc_time_T *      _loc P((void));
-#define Locale _loc()
-#endif /* defined LOCALE_HOME */
-#ifndef LOCALE_HOME
-#define Locale (&C_time_locale)
-#endif /* !defined LOCALE_HOME */
-
-static const struct lc_time_T  C_time_locale = {
-       {
-               "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-       }, {
-               "January", "February", "March", "April", "May", "June",
-               "July", "August", "September", "October", "November", "December"
-       }, {
-               "Sun", "Mon", "Tue", "Wed",
-               "Thu", "Fri", "Sat"
-       }, {
-               "Sunday", "Monday", "Tuesday", "Wednesday",
-               "Thursday", "Friday", "Saturday"
-       },
-
-       /* X_fmt */
-       "%H:%M:%S",
-
-       /*
-       ** x_fmt
-       ** C99 requires this format.
-       ** Using just numbers (as here) makes Quakers happier;
-       ** it's also compatible with SVR4.
-       */
-       "%m/%d/%y",
-
-       /*
-       ** c_fmt
-       ** C99 requires this format.
-       ** Previously this code used "%D %X", but we now conform to C99.
-       ** Note that
-       **      "%a %b %d %H:%M:%S %Y"
-       ** is used by Solaris 2.3.
-       */
-       "%a %b %e %T %Y",
-
-       /* am */
-       "AM",
-
-       /* pm */
-       "PM",
-
-       /* date_fmt */
-       "%a %b %e %H:%M:%S %Z %Y"
-};
-
 static char *  _add P((const char *, char *, const char *));
 static char *  _conv P((int, const char *, char *, const char *));
 static char *  _fmt P((const char *, const struct tm *, char *, const char *,
@@ -123,6 +57,8 @@
 #define IN_THIS        2
 #define IN_ALL 3
 
+#define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
+
 size_t
 strftime(s, maxsize, format, t)
 char * const           s;
@@ -134,9 +70,6 @@
        int     warn;
 
        tzset();
-#ifdef LOCALE_HOME
-       localebuf.mon[0] = 0;
-#endif /* defined LOCALE_HOME */
        warn = IN_NONE;
        p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
 #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
@@ -641,124 +574,3 @@
                pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
        return pt;
 }
-
-#ifdef LOCALE_HOME
-static struct lc_time_T *
-_loc P((void))
-{
-       static const char       locale_home[] = LOCALE_HOME;
-       static const char       lc_time[] = "LC_TIME";
-       static char *           locale_buf;
-
-       int                     fd;
-       int                     oldsun; /* "...ain't got nothin' to do..." */
-       char *                  lbuf;
-       char *                  name;
-       char *                  p;
-       const char **           ap;
-       const char *            plim;
-       char                    filename[FILENAME_MAX];
-       struct stat             st;
-       size_t                  namesize;
-       size_t                  bufsize;
-
-       /*
-       ** Use localebuf.mon[0] to signal whether locale is already set up.
-       */
-       if (localebuf.mon[0])
-               return &localebuf;
-       name = setlocale(LC_TIME, (char *) NULL);
-       if (name == NULL || *name == '\0')
-               goto no_locale;
-       /*
-       ** If the locale name is the same as our cache, use the cache.
-       */
-       lbuf = locale_buf;
-       if (lbuf != NULL && strcmp(name, lbuf) == 0) {
-               p = lbuf;
-               for (ap = (const char **) &localebuf;
-                       ap < (const char **) (&localebuf + 1);
-                               ++ap)
-                                       *ap = p += strlen(p) + 1;
-               return &localebuf;
-       }
-       /*
-       ** Slurp the locale file into the cache.
-       */
-       namesize = strlen(name) + 1;
-       if (sizeof filename <
-               ((sizeof locale_home) + namesize + (sizeof lc_time)))
-                       goto no_locale;
-       oldsun = 0;
-       (void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time);
-       fd = open(filename, O_RDONLY);
-       if (fd < 0) {
-               /*
-               ** Old Sun systems have a different naming and data convention.
-               */
-               oldsun = 1;
-               (void) sprintf(filename, "%s/%s/%s", locale_home,
-                       lc_time, name);
-               fd = open(filename, O_RDONLY);
-               if (fd < 0)
-                       goto no_locale;
-       }
-       if (fstat(fd, &st) != 0)
-               goto bad_locale;
-       if (st.st_size <= 0)
-               goto bad_locale;
-       bufsize = namesize + st.st_size;
-       locale_buf = NULL;
-       lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize);
-       if (lbuf == NULL)
-               goto bad_locale;
-       (void) strcpy(lbuf, name);
-       p = lbuf + namesize;
-       plim = p + st.st_size;
-       if (read(fd, p, (size_t) st.st_size) != st.st_size)
-               goto bad_lbuf;
-       if (close(fd) != 0)
-               goto bad_lbuf;
-       /*
-       ** Parse the locale file into localebuf.
-       */
-       if (plim[-1] != '\n')
-               goto bad_lbuf;
-       for (ap = (const char **) &localebuf;
-               ap < (const char **) (&localebuf + 1);
-                       ++ap) {
-                               if (p == plim)
-                                       goto bad_lbuf;
-                               *ap = p;
-                               while (*p != '\n')
-                                       ++p;
-                               *p++ = '\0';
-       }
-       if (oldsun) {
-               /*
-               ** SunOS 4 used an obsolescent format; see localdtconv(3).
-               ** c_fmt had the ``short format for dates and times together''
-               ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
-               ** date_fmt had the ``long format for dates''
-               ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
-               ** Discard the latter in favor of the former.
-               */
-               localebuf.date_fmt = localebuf.c_fmt;
-       }
-       /*
-       ** Record the successful parse in the cache.
-       */
-       locale_buf = lbuf;
-
-       return &localebuf;
-
-bad_lbuf:
-       free(lbuf);
-bad_locale:
-       (void) close(fd);
-no_locale:
-       localebuf = C_time_locale;
-       locale_buf = NULL;
-       return &localebuf;
-}
-#endif /* defined LOCALE_HOME */

[... truncated: 194 lines follow ...]

Other related posts:

  • » [haiku-commits] r36341 - in haiku/branches/developer/zooey/posix-locale: headers/private/libroot headers/private/libroot/locale headers/private/libroot/time src/system/libroot/posix/locale src/system/libroot/posix/time ... - zooey