home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / i18n / dtfmtsym.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  18.5 KB  |  527 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright Taligent, Inc.,  1997                                       *
  6. *   (C) Copyright International Business Machines Corporation,  1997-1998     *
  7. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  8. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  9. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  10. *                                                                             *
  11. *******************************************************************************
  12. *
  13. * File DTFMTSYM.CPP
  14. *
  15. * Modification History:
  16. *
  17. *   Date        Name        Description
  18. *   02/19/97    aliu        Converted from java.
  19. *   07/21/98    stephen     Added getZoneIndex
  20. *                            Changed weekdays/short weekdays to be one-based
  21. *   06/14/99    stephen     Removed SimpleDateFormat::fgTimeZoneDataSuffix
  22. *******************************************************************************
  23. */
  24.  
  25. #include "dtfmtsym.h"
  26. #include "resbund.h"
  27. #include "smpdtfmt.h"
  28. #include "mutex.h"
  29.  
  30. // *****************************************************************************
  31. // class DateFormatSymbols
  32. // *****************************************************************************
  33.  
  34. // generic date-format pattern symbols.  For their meanings, see class docs
  35. // for SimpleDateFormat
  36. UnicodeString DateFormatSymbols::fgPatternChars = "GyMdkHmsSEDFwWahKz";
  37.  
  38. //------------------------------------------------------
  39. // Strings of last resort.  These are only used if we have no resource
  40. // files.  They aren't designed for actual use, just for backup.
  41.  
  42. //============================================================
  43. // To make the VC++ compiler happy these must occur before the
  44. // sizeof operations on the arrays occur below.
  45. //============================================================
  46.  
  47. // These are the month names and abbreviations of last resort.
  48. const UnicodeString DateFormatSymbols::fgLastResortMonthNames[] =
  49. {
  50.     "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13"
  51. };
  52.  
  53. // These are the weekday names and abbreviations of last resort.
  54. const UnicodeString DateFormatSymbols::fgLastResortDayNames[] =
  55. {
  56.     "", "1", "2", "3", "4", "5", "6", "7"
  57. };
  58.  
  59. // These are the am/pm and BC/AD markers of last resort.
  60. const UnicodeString DateFormatSymbols::fgLastResortAmPmMarkers[] =
  61. {
  62.     "AM", "PM"
  63. };
  64.  
  65. const UnicodeString DateFormatSymbols::fgLastResortEras[] =
  66. {
  67.     "BC", "AD"
  68. };
  69.  
  70. // These are the zone strings of last resort.
  71. UnicodeString** DateFormatSymbols::fgLastResortZoneStringsH = 0;
  72.  
  73. const UnicodeString DateFormatSymbols::fgLastResortZoneStrings[] =
  74. {
  75.     "GMT", "GMT", "GMT", "GMT", "GMT"
  76. };
  77.  
  78. //------------------------------------------------------
  79.  
  80. DateFormatSymbols::DateFormatSymbols(const Locale& locale,
  81.                                      UErrorCode& status)
  82. {
  83.     initializeData(locale, status);
  84. }
  85.  
  86. DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
  87. {
  88.     initializeData(Locale::getDefault(), status, TRUE);
  89. }
  90.  
  91. DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
  92. {
  93.     fIsOwned = 0; // We own nothing (ignore existing pointers)
  94.     *this = other;
  95. }
  96.  
  97. void
  98. DateFormatSymbols::assignArray(UnicodeString*& dstArray,
  99.                                int32_t& dstCount,
  100.                                const UnicodeString* srcArray,
  101.                                int32_t srcCount,
  102.                                const DateFormatSymbols& other,
  103.                                int32_t which)
  104. {
  105.     // duplicates or aliases the source array, depending on the status of
  106.     // the appropriate isOwned flag
  107.     bool_t owned = other.isOwned(which);
  108.     setIsOwned(which, owned);
  109.     dstCount = srcCount;
  110.     if (owned)
  111.     {
  112.         dstArray = new UnicodeString[srcCount];
  113.         icu_arrayCopy(srcArray, dstArray, srcCount);
  114.     }
  115.     else
  116.     {
  117.         dstArray = (UnicodeString*)srcArray; // Compiler requires cast
  118.     }
  119. }
  120.  
  121. /**
  122.  * Create a copy, in fZoneStrings, of the given zone strings array.  The
  123.  * member variables fZoneStringsRowCount and fZoneStringsColCount should
  124.  * be set already by the caller.  The fIsOwned flags are not checked or set
  125.  * by this method; that is the caller's responsibility.
  126.  */
  127. void
  128. DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
  129. {
  130.     fZoneStrings = new UnicodeString*[fZoneStringsRowCount];
  131.     for (int32_t row=0; row<fZoneStringsRowCount; ++row)
  132.     {
  133.         fZoneStrings[row] = new UnicodeString[fZoneStringsColCount];
  134.         icu_arrayCopy(otherStrings[row], fZoneStrings[row], fZoneStringsColCount);
  135.     }
  136. }
  137.  
  138. /**
  139.  * Assignment operator.  A bit messy because the other object may or may not
  140.  * own each of its arrays.  We then alias or copy those arrays as appropriate.
  141.  * Arrays that aren't owned are assumed to be permanently "around," which is
  142.  * true, since they are owned by the ResourceBundle cache.
  143.  */
  144. DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
  145. {
  146.     dispose();
  147.     assignArray(fEras, fErasCount, other.fEras, other.fErasCount, other, kEras);
  148.     assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount, other, kMonths);
  149.     assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount, other, kShortMonths);
  150.     assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount, other, kWeekdays);
  151.     assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount, other, kShortWeekdays);
  152.     assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount, other, kAmPms);
  153.  
  154.     bool_t owned = other.isOwned(kZoneStrings);
  155.     setIsOwned(kZoneStrings, owned);
  156.     fZoneStringsRowCount = other.fZoneStringsRowCount;
  157.     fZoneStringsColCount = other.fZoneStringsColCount;
  158.     if (owned) createZoneStrings((const UnicodeString**)other.fZoneStrings);
  159.         else fZoneStrings = other.fZoneStrings;
  160.  
  161.     fLocalPatternChars = other.fLocalPatternChars;
  162.     return *this;
  163. }
  164.  
  165. DateFormatSymbols::~DateFormatSymbols()
  166. {
  167.     dispose();
  168. }
  169.  
  170. void DateFormatSymbols::dispose()
  171. {
  172.     // Delete those items which we have marked as owned
  173.  
  174.     if (isOwned(kEras))             delete[] fEras;
  175.     if (isOwned(kMonths))           delete[] fMonths;
  176.     if (isOwned(kShortMonths))      delete[] fShortMonths;
  177.     if (isOwned(kWeekdays))         delete[] fWeekdays;
  178.     if (isOwned(kShortWeekdays))    delete[] fShortWeekdays;
  179.     if (isOwned(kAmPms))            delete[] fAmPms;
  180.     
  181.     disposeZoneStrings();
  182.  
  183.     fIsOwned = 0; // Indicate that we no longer need to delete anything
  184. }
  185.  
  186. void DateFormatSymbols::disposeZoneStrings()
  187. {
  188.     if (isOwned(kZoneStrings))
  189.     {
  190.         for (int32_t row=0; row<fZoneStringsRowCount; ++row)
  191.             delete[] fZoneStrings[row];
  192.         delete[] fZoneStrings;
  193.     }
  194. }
  195.  
  196. bool_t
  197. DateFormatSymbols::arrayCompare(const UnicodeString* array1,
  198.                                 const UnicodeString* array2,
  199.                                 int32_t count)
  200. {
  201.     if (array1 == array2) return TRUE;
  202.     while (count>0)
  203.     {
  204.         --count;
  205.         if (array1[count] != array2[count]) return FALSE;
  206.     }
  207.     return TRUE;
  208. }
  209.  
  210. bool_t
  211. DateFormatSymbols::operator==(const DateFormatSymbols& other) const
  212. {
  213.     // First do cheap comparisons
  214.     if (fErasCount == other.fErasCount &&
  215.         fMonthsCount == other.fMonthsCount &&
  216.         fShortMonthsCount == other.fShortMonthsCount &&
  217.         fWeekdaysCount == other.fWeekdaysCount &&
  218.         fShortWeekdaysCount == other.fShortWeekdaysCount &&
  219.         fAmPmsCount == other.fAmPmsCount &&
  220.         fZoneStringsRowCount == other.fZoneStringsRowCount &&
  221.         fZoneStringsColCount == other.fZoneStringsColCount)
  222.     {
  223.         // Now compare the arrays themselves
  224.         if (arrayCompare(fEras, other.fEras, fErasCount) &&
  225.             arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
  226.             arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
  227.             arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
  228.             arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
  229.             arrayCompare(fAmPms, other.fAmPms, fAmPmsCount))
  230.         {
  231.             if (fZoneStrings == other.fZoneStrings) return TRUE;
  232.  
  233.             for (int32_t row=0; row<fZoneStringsRowCount; ++row)
  234.             {
  235.                 if (!arrayCompare(fZoneStrings[row], other.fZoneStrings[row], fZoneStringsColCount))
  236.                     return FALSE;
  237.             }
  238.             return TRUE;
  239.         }
  240.     }
  241.     return FALSE;
  242. }
  243.  
  244. //------------------------------------------------------
  245.  
  246. const UnicodeString*
  247. DateFormatSymbols::getEras(int32_t &count) const
  248. {
  249.     count = fErasCount;
  250.     return fEras;
  251. }
  252.  
  253. const UnicodeString*
  254. DateFormatSymbols::getMonths(int32_t &count) const
  255. {
  256.     count = fMonthsCount;
  257.     return fMonths;
  258. }
  259.  
  260. const UnicodeString*
  261. DateFormatSymbols::getShortMonths(int32_t &count) const
  262. {
  263.     count = fShortMonthsCount;
  264.     return fShortMonths;
  265. }
  266.  
  267. const UnicodeString*
  268. DateFormatSymbols::getWeekdays(int32_t &count) const
  269. {
  270.     count = fWeekdaysCount;
  271.     return fWeekdays;
  272. }
  273.  
  274. const UnicodeString*
  275. DateFormatSymbols::getShortWeekdays(int32_t &count) const
  276. {
  277.     count = fShortWeekdaysCount;
  278.     return fShortWeekdays;
  279. }
  280.  
  281. const UnicodeString*
  282. DateFormatSymbols::getAmPmStrings(int32_t &count) const
  283. {
  284.     count = fAmPmsCount;
  285.     return fAmPms;
  286. }
  287.  
  288. //------------------------------------------------------
  289.  
  290. void
  291. DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
  292. {
  293.     // delete the old list if we own it
  294.     if (isOwned(kEras)) delete[] fEras;
  295.  
  296.     // we always own the new list, which we create here (we duplicate rather
  297.     // than adopting the list passed in)
  298.     setIsOwned(kEras, TRUE);
  299.     fEras = new UnicodeString[count];
  300.     icu_arrayCopy(erasArray,fEras,  count);
  301.     fErasCount = count;
  302. }
  303.  
  304. void
  305. DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
  306. {
  307.     // delete the old list if we own it
  308.     if (isOwned(kMonths)) delete[] fMonths;
  309.  
  310.     // we always own the new list, which we create here (we duplicate rather
  311.     // than adopting the list passed in)
  312.     setIsOwned(kMonths, TRUE);
  313.     fMonths = new UnicodeString[count];
  314.     icu_arrayCopy( monthsArray,fMonths,count);
  315.     fMonthsCount = count;
  316. }
  317.  
  318. void
  319. DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
  320. {
  321.     // delete the old list if we own it
  322.     if (isOwned(kShortMonths)) delete[] fShortMonths;
  323.  
  324.     // we always own the new list, which we create here (we duplicate rather
  325.     // than adopting the list passed in)
  326.     setIsOwned(kShortMonths, TRUE);
  327.     fShortMonths = new UnicodeString[count];
  328.     icu_arrayCopy(shortMonthsArray,fShortMonths,  count);
  329.     fShortMonthsCount = count;
  330. }
  331.  
  332. void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
  333. {
  334.     // delete the old list if we own it
  335.     if (isOwned(kWeekdays)) delete[] fWeekdays;
  336.  
  337.     // we always own the new list, which we create here (we duplicate rather
  338.     // than adopting the list passed in)
  339.     setIsOwned(kWeekdays, TRUE);
  340.     fWeekdays = new UnicodeString[count];
  341.     icu_arrayCopy(weekdaysArray,fWeekdays,count);
  342.     fWeekdaysCount = count;
  343. }
  344.  
  345. void
  346. DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
  347. {
  348.     // delete the old list if we own it
  349.     if (isOwned(kShortWeekdays)) delete[] fShortWeekdays;
  350.  
  351.     // we always own the new list, which we create here (we duplicate rather
  352.     // than adopting the list passed in)
  353.     setIsOwned(kShortWeekdays, TRUE);
  354.     fShortWeekdays = new UnicodeString[count];
  355.     icu_arrayCopy( shortWeekdaysArray,fShortWeekdays,count);
  356.     fShortWeekdaysCount = count;
  357. }
  358.  
  359. void
  360. DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
  361. {
  362.     // delete the old list if we own it
  363.     if (isOwned(kAmPms)) delete[] fAmPms;
  364.  
  365.     // we always own the new list, which we create here (we duplicate rather
  366.     // than adopting the list passed in)
  367.     setIsOwned(kAmPms, TRUE);
  368.     fAmPms = new UnicodeString[count];
  369.     icu_arrayCopy(amPmsArray,fAmPms,count);
  370.     fAmPmsCount = count;
  371. }
  372.  
  373. //------------------------------------------------------
  374.  
  375. const UnicodeString**
  376. DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
  377. {
  378.     rowCount = fZoneStringsRowCount;
  379.     columnCount = fZoneStringsColCount;
  380.     return (const UnicodeString**)fZoneStrings; // Compiler requires cast
  381. }
  382.  
  383. void
  384. DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
  385. {
  386.     // since deleting a 2-d array is a pain in the butt, we offload that task to
  387.     // a separate function
  388.     disposeZoneStrings();
  389.  
  390.     // we always own the new list, which we create here (we duplicate rather
  391.     // than adopting the list passed in)
  392.     setIsOwned(kZoneStrings, TRUE);
  393.     fZoneStringsRowCount = rowCount;
  394.     fZoneStringsColCount = columnCount;
  395.     createZoneStrings((const UnicodeString**)strings);
  396. }
  397.  
  398. //------------------------------------------------------
  399.  
  400. UnicodeString&
  401. DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
  402. {
  403.     result = fLocalPatternChars;
  404.     return result;
  405. }
  406.  
  407. //------------------------------------------------------
  408.  
  409. void
  410. DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
  411. {
  412.     fLocalPatternChars = newLocalPatternChars;
  413. }
  414.  
  415. //------------------------------------------------------
  416.  
  417. void
  418. DateFormatSymbols::initializeData(const Locale& locale, UErrorCode& status, bool_t useLastResortData)
  419. {
  420.     if (U_FAILURE(status)) return;
  421.  
  422.     fIsOwned = 0; // Nothing is owned
  423.  
  424.     /**
  425.      * Retrieve the string arrays we need from the resource bundle file.
  426.      * We cast away const here, but that's okay; we won't delete any of
  427.      * these.
  428.      */
  429.     ResourceBundle resource(Locale::getDataDirectory(), locale, status);
  430.     if (U_FAILURE(status))
  431.     {
  432.         if (useLastResortData)
  433.         {
  434.             // Handle the case in which there is no resource data present.
  435.             // We don't have to generate usable patterns in this situation;
  436.             // we just need to produce something that will be semi-intelligible
  437.             // in most locales.
  438.  
  439.             status = U_USING_FALLBACK_ERROR;
  440.  
  441.             fEras = (UnicodeString*)fgLastResortEras;
  442.             fErasCount = sizeof(fgLastResortEras[0]) / sizeof(fgLastResortEras[0]);
  443.             fMonths = fShortMonths = (UnicodeString*)fgLastResortMonthNames;
  444.             fMonthsCount = fShortMonthsCount = sizeof(fgLastResortMonthNames) / sizeof(fgLastResortMonthNames[0]);
  445.             fWeekdays = fShortWeekdays = (UnicodeString*)fgLastResortDayNames;
  446.             fWeekdaysCount = fShortWeekdaysCount = sizeof(fgLastResortDayNames) / sizeof(fgLastResortDayNames[0]);
  447.             fAmPms = (UnicodeString*)fgLastResortAmPmMarkers;
  448.             fAmPmsCount = sizeof(fgLastResortAmPmMarkers) / sizeof(fgLastResortAmPmMarkers[0]);
  449.             if (fgLastResortZoneStringsH == 0)
  450.             {
  451.                 // Initialize this -- the compiler doesn't like to do so at static init time
  452.                 UnicodeString **tempH = fgLastResortZoneStringsH = new UnicodeString*[1];
  453.  
  454.                 Mutex lock; // This could be optimized but it's not worth it -- exceptional case
  455.                 *fgLastResortZoneStringsH = (UnicodeString*)fgLastResortZoneStrings;
  456.             }
  457.             fZoneStrings = fgLastResortZoneStringsH;
  458.             fZoneStringsRowCount = 1;
  459.             fZoneStringsColCount = sizeof(fgLastResortZoneStrings);
  460.             fLocalPatternChars = fgPatternChars;
  461.         }
  462.         return;
  463.     }
  464.  
  465.     // if we make it to here, the resource data is cool, and we can get everything out
  466.     // of it that we need except for the time-zone and localized-pattern data, which
  467.     // are stoerd in a separate file
  468.     fEras           = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgErasTag, fErasCount, status);
  469.     fMonths         = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgMonthNamesTag, fMonthsCount, status);
  470.     fShortMonths    = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgMonthAbbreviationsTag, fShortMonthsCount, status);
  471.     // {sfb} fixed to handle 1-based weekdays
  472.     UnicodeString *lWeekdays = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgDayNamesTag, fWeekdaysCount, status);
  473.     fWeekdays = new UnicodeString [8];
  474.     fWeekdays[0] = UnicodeString("");
  475.     icu_arrayCopy(lWeekdays, 0, fWeekdays, 1, 7);
  476.     setIsOwned(kWeekdays, TRUE);
  477.     //fWeekdays       = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgDayNamesTag, fWeekdaysCount, status);
  478.  
  479.     UnicodeString *lSWeekdays = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgDayAbbreviationsTag, fShortWeekdaysCount, status);
  480.     fShortWeekdays = new UnicodeString [8];
  481.     fShortWeekdays[0] = UnicodeString("");
  482.     icu_arrayCopy(lSWeekdays, 0, fShortWeekdays, 1, 7);
  483.     setIsOwned(kShortWeekdays, TRUE);
  484.     //fShortWeekdays  = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgDayAbbreviationsTag, fShortWeekdaysCount, status);
  485.  
  486.     fWeekdaysCount = fShortWeekdaysCount = 8;
  487.     
  488.     fAmPms          = (UnicodeString*)resource.getStringArray(SimpleDateFormat::fgAmPmMarkersTag, fAmPmsCount, status);
  489.  
  490.     /**
  491.      * Retrieve the data we need from the time zone data file.
  492.      * We cast away const here, but that's okay; we won't delete any of
  493.      * these.
  494.      */
  495.     ResourceBundle zoneResource(Locale::getDataDirectory(), locale, status);
  496.     fZoneStrings    = (UnicodeString**)zoneResource.get2dArray(SimpleDateFormat::fgZoneStringsTag, fZoneStringsRowCount, fZoneStringsColCount, status);
  497.     zoneResource.getString(SimpleDateFormat::fgLocalPatternCharsTag, fLocalPatternChars, status);
  498. }
  499.  
  500. /**
  501.  * Package private: used by SimpleDateFormat
  502.  * Gets the index for the given time zone ID to obtain the timezone
  503.  * strings for formatting. The time zone ID is just for programmatic
  504.  * lookup. NOT LOCALIZED!!!
  505.  * @param ID the given time zone ID.
  506.  * @return the index of the given time zone ID.  Returns -1 if
  507.  * the given time zone ID can't be located in the DateFormatSymbols object.
  508.  * @see java.util.SimpleTimeZone
  509.  */
  510. int32_t DateFormatSymbols::getZoneIndex(const UnicodeString& ID) const
  511. {
  512.     // {sfb} kludge to support case-insensitive comparison
  513.     UnicodeString lcaseID(ID);
  514.     lcaseID.toLower();
  515.     
  516.     for(int32_t index = 0; index < fZoneStringsRowCount; index++) {
  517.         UnicodeString lcase(fZoneStrings[index][0]);
  518.         lcase.toLower();
  519.         if (lcaseID == lcase) 
  520.             return index;
  521.     }
  522.  
  523.     return -1;
  524. }
  525.  
  526. //eof
  527.