LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - dayperiodrules.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 265 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             : *******************************************************************************
       5             : * Copyright (C) 2016, International Business Machines
       6             : * Corporation and others.  All Rights Reserved.
       7             : *******************************************************************************
       8             : * dayperiodrules.cpp
       9             : *
      10             : * created on: 2016-01-20
      11             : * created by: kazede
      12             : */
      13             : 
      14             : #include "dayperiodrules.h"
      15             : 
      16             : #include "unicode/ures.h"
      17             : #include "charstr.h"
      18             : #include "cstring.h"
      19             : #include "ucln_in.h"
      20             : #include "uhash.h"
      21             : #include "umutex.h"
      22             : #include "uresimp.h"
      23             : 
      24             : 
      25             : U_NAMESPACE_BEGIN
      26             : 
      27             : namespace {
      28             : 
      29             : struct DayPeriodRulesData : public UMemory {
      30           0 :     DayPeriodRulesData() : localeToRuleSetNumMap(NULL), rules(NULL), maxRuleSetNum(0) {}
      31             : 
      32             :     UHashtable *localeToRuleSetNumMap;
      33             :     DayPeriodRules *rules;
      34             :     int32_t maxRuleSetNum;
      35             : } *data = NULL;
      36             : 
      37             : enum CutoffType {
      38             :     CUTOFF_TYPE_UNKNOWN = -1,
      39             :     CUTOFF_TYPE_BEFORE,
      40             :     CUTOFF_TYPE_AFTER,  // TODO: AFTER is deprecated in CLDR 29. Remove.
      41             :     CUTOFF_TYPE_FROM,
      42             :     CUTOFF_TYPE_AT
      43             : };
      44             : 
      45             : } // namespace
      46             : 
      47             : struct DayPeriodRulesDataSink : public ResourceSink {
      48           0 :     DayPeriodRulesDataSink() {
      49           0 :         for (int32_t i = 0; i < UPRV_LENGTHOF(cutoffs); ++i) { cutoffs[i] = 0; }
      50           0 :     }
      51             :     virtual ~DayPeriodRulesDataSink();
      52             : 
      53           0 :     virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
      54           0 :         ResourceTable dayPeriodData = value.getTable(errorCode);
      55           0 :         if (U_FAILURE(errorCode)) { return; }
      56             : 
      57           0 :         for (int32_t i = 0; dayPeriodData.getKeyAndValue(i, key, value); ++i) {
      58           0 :             if (uprv_strcmp(key, "locales") == 0) {
      59           0 :                 ResourceTable locales = value.getTable(errorCode);
      60           0 :                 if (U_FAILURE(errorCode)) { return; }
      61             : 
      62           0 :                 for (int32_t j = 0; locales.getKeyAndValue(j, key, value); ++j) {
      63           0 :                     UnicodeString setNum_str = value.getUnicodeString(errorCode);
      64           0 :                     int32_t setNum = parseSetNum(setNum_str, errorCode);
      65           0 :                     uhash_puti(data->localeToRuleSetNumMap, const_cast<char *>(key), setNum, &errorCode);
      66             :                 }
      67           0 :             } else if (uprv_strcmp(key, "rules") == 0) {
      68             :                 // Allocate one more than needed to skip [0]. See comment in parseSetNum().
      69           0 :                 data->rules = new DayPeriodRules[data->maxRuleSetNum + 1];
      70           0 :                 if (data->rules == NULL) {
      71           0 :                     errorCode = U_MEMORY_ALLOCATION_ERROR;
      72           0 :                     return;
      73             :                 }
      74           0 :                 ResourceTable rules = value.getTable(errorCode);
      75           0 :                 processRules(rules, key, value, errorCode);
      76           0 :                 if (U_FAILURE(errorCode)) { return; }
      77             :             }
      78             :         }
      79             :     }
      80             : 
      81           0 :     void processRules(const ResourceTable &rules, const char *key,
      82             :                       ResourceValue &value, UErrorCode &errorCode) {
      83           0 :         if (U_FAILURE(errorCode)) { return; }
      84             : 
      85           0 :         for (int32_t i = 0; rules.getKeyAndValue(i, key, value); ++i) {
      86           0 :             ruleSetNum = parseSetNum(key, errorCode);
      87           0 :             ResourceTable ruleSet = value.getTable(errorCode);
      88           0 :             if (U_FAILURE(errorCode)) { return; }
      89             : 
      90           0 :             for (int32_t j = 0; ruleSet.getKeyAndValue(j, key, value); ++j) {
      91           0 :                 period = DayPeriodRules::getDayPeriodFromString(key);
      92           0 :                 if (period == DayPeriodRules::DAYPERIOD_UNKNOWN) {
      93           0 :                     errorCode = U_INVALID_FORMAT_ERROR;
      94           0 :                     return;
      95             :                 }
      96           0 :                 ResourceTable periodDefinition = value.getTable(errorCode);
      97           0 :                 if (U_FAILURE(errorCode)) { return; }
      98             : 
      99           0 :                 for (int32_t k = 0; periodDefinition.getKeyAndValue(k, key, value); ++k) {
     100           0 :                     if (value.getType() == URES_STRING) {
     101             :                         // Key-value pairs (e.g. before{6:00}).
     102           0 :                         CutoffType type = getCutoffTypeFromString(key);
     103           0 :                         addCutoff(type, value.getUnicodeString(errorCode), errorCode);
     104           0 :                         if (U_FAILURE(errorCode)) { return; }
     105             :                     } else {
     106             :                         // Arrays (e.g. before{6:00, 24:00}).
     107           0 :                         cutoffType = getCutoffTypeFromString(key);
     108           0 :                         ResourceArray cutoffArray = value.getArray(errorCode);
     109           0 :                         if (U_FAILURE(errorCode)) { return; }
     110             : 
     111           0 :                         int32_t length = cutoffArray.getSize();
     112           0 :                         for (int32_t l = 0; l < length; ++l) {
     113           0 :                             cutoffArray.getValue(l, value);
     114           0 :                             addCutoff(cutoffType, value.getUnicodeString(errorCode), errorCode);
     115           0 :                             if (U_FAILURE(errorCode)) { return; }
     116             :                         }
     117             :                     }
     118             :                 }
     119           0 :                 setDayPeriodForHoursFromCutoffs(errorCode);
     120           0 :                 for (int32_t k = 0; k < UPRV_LENGTHOF(cutoffs); ++k) {
     121           0 :                     cutoffs[k] = 0;
     122             :                 }
     123             :             }
     124             : 
     125           0 :             if (!data->rules[ruleSetNum].allHoursAreSet()) {
     126           0 :                 errorCode = U_INVALID_FORMAT_ERROR;
     127           0 :                 return;
     128             :             }
     129             :         }
     130             :     }
     131             : 
     132             :     // Members.
     133             :     int32_t cutoffs[25];  // [0] thru [24]: 24 is allowed in "before 24".
     134             : 
     135             :     // "Path" to data.
     136             :     int32_t ruleSetNum;
     137             :     DayPeriodRules::DayPeriod period;
     138             :     CutoffType cutoffType;
     139             : 
     140             :     // Helpers.
     141           0 :     static int32_t parseSetNum(const UnicodeString &setNumStr, UErrorCode &errorCode) {
     142           0 :         CharString cs;
     143           0 :         cs.appendInvariantChars(setNumStr, errorCode);
     144           0 :         return parseSetNum(cs.data(), errorCode);
     145             :     }
     146             : 
     147           0 :     static int32_t parseSetNum(const char *setNumStr, UErrorCode &errorCode) {
     148           0 :         if (U_FAILURE(errorCode)) { return -1; }
     149             : 
     150           0 :         if (uprv_strncmp(setNumStr, "set", 3) != 0) {
     151           0 :             errorCode = U_INVALID_FORMAT_ERROR;
     152           0 :             return -1;
     153             :         }
     154             : 
     155           0 :         int32_t i = 3;
     156           0 :         int32_t setNum = 0;
     157           0 :         while (setNumStr[i] != 0) {
     158           0 :             int32_t digit = setNumStr[i] - '0';
     159           0 :             if (digit < 0 || 9 < digit) {
     160           0 :                 errorCode = U_INVALID_FORMAT_ERROR;
     161           0 :                 return -1;
     162             :             }
     163           0 :             setNum = 10 * setNum + digit;
     164           0 :             ++i;
     165             :         }
     166             : 
     167             :         // Rule set number must not be zero. (0 is used to indicate "not found" by hashmap.)
     168             :         // Currently ICU data conveniently starts numbering rule sets from 1.
     169           0 :         if (setNum == 0) {
     170           0 :             errorCode = U_INVALID_FORMAT_ERROR;
     171           0 :             return -1;
     172             :         } else {
     173           0 :             return setNum;
     174             :         }
     175             :     }
     176             : 
     177           0 :     void addCutoff(CutoffType type, const UnicodeString &hour_str, UErrorCode &errorCode) {
     178           0 :         if (U_FAILURE(errorCode)) { return; }
     179             : 
     180           0 :         if (type == CUTOFF_TYPE_UNKNOWN) {
     181           0 :             errorCode = U_INVALID_FORMAT_ERROR;
     182           0 :             return;
     183             :         }
     184             : 
     185           0 :         int32_t hour = parseHour(hour_str, errorCode);
     186           0 :         if (U_FAILURE(errorCode)) { return; }
     187             : 
     188           0 :         cutoffs[hour] |= 1 << type;
     189             :     }
     190             : 
     191             :     // Translate the cutoffs[] array to day period rules.
     192           0 :     void setDayPeriodForHoursFromCutoffs(UErrorCode &errorCode) {
     193           0 :         DayPeriodRules &rule = data->rules[ruleSetNum];
     194             : 
     195           0 :         for (int32_t startHour = 0; startHour <= 24; ++startHour) {
     196             :             // AT cutoffs must be either midnight or noon.
     197           0 :             if (cutoffs[startHour] & (1 << CUTOFF_TYPE_AT)) {
     198           0 :                 if (startHour == 0 && period == DayPeriodRules::DAYPERIOD_MIDNIGHT) {
     199           0 :                     rule.fHasMidnight = TRUE;
     200           0 :                 } else if (startHour == 12 && period == DayPeriodRules::DAYPERIOD_NOON) {
     201           0 :                     rule.fHasNoon = TRUE;
     202             :                 } else {
     203           0 :                     errorCode = U_INVALID_FORMAT_ERROR;  // Bad data.
     204           0 :                     return;
     205             :                 }
     206             :             }
     207             : 
     208             :             // FROM/AFTER and BEFORE must come in a pair.
     209           0 :             if (cutoffs[startHour] & (1 << CUTOFF_TYPE_FROM) ||
     210           0 :                     cutoffs[startHour] & (1 << CUTOFF_TYPE_AFTER)) {
     211           0 :                 for (int32_t hour = startHour + 1;; ++hour) {
     212           0 :                     if (hour == startHour) {
     213             :                         // We've gone around the array once and can't find a BEFORE.
     214           0 :                         errorCode = U_INVALID_FORMAT_ERROR;
     215           0 :                         return;
     216             :                     }
     217           0 :                     if (hour == 25) { hour = 0; }
     218           0 :                     if (cutoffs[hour] & (1 << CUTOFF_TYPE_BEFORE)) {
     219           0 :                         rule.add(startHour, hour, period);
     220           0 :                         break;
     221             :                     }
     222             :                 }
     223             :             }
     224             :         }
     225             :     }
     226             : 
     227             :     // Translate "before" to CUTOFF_TYPE_BEFORE, for example.
     228           0 :     static CutoffType getCutoffTypeFromString(const char *type_str) {
     229           0 :         if (uprv_strcmp(type_str, "from") == 0) {
     230           0 :             return CUTOFF_TYPE_FROM;
     231           0 :         } else if (uprv_strcmp(type_str, "before") == 0) {
     232           0 :             return CUTOFF_TYPE_BEFORE;
     233           0 :         } else if (uprv_strcmp(type_str, "after") == 0) {
     234           0 :             return CUTOFF_TYPE_AFTER;
     235           0 :         } else if (uprv_strcmp(type_str, "at") == 0) {
     236           0 :             return CUTOFF_TYPE_AT;
     237             :         } else {
     238           0 :             return CUTOFF_TYPE_UNKNOWN;
     239             :         }
     240             :     }
     241             : 
     242             :     // Gets the numerical value of the hour from the Unicode string.
     243           0 :     static int32_t parseHour(const UnicodeString &time, UErrorCode &errorCode) {
     244           0 :         if (U_FAILURE(errorCode)) {
     245           0 :             return 0;
     246             :         }
     247             : 
     248           0 :         int32_t hourLimit = time.length() - 3;
     249             :         // `time` must look like "x:00" or "xx:00".
     250             :         // If length is wrong or `time` doesn't end with ":00", error out.
     251           0 :         if ((hourLimit != 1 && hourLimit != 2) ||
     252           0 :                 time[hourLimit] != 0x3A || time[hourLimit + 1] != 0x30 ||
     253           0 :                 time[hourLimit + 2] != 0x30) {
     254           0 :             errorCode = U_INVALID_FORMAT_ERROR;
     255           0 :             return 0;
     256             :         }
     257             : 
     258             :         // If `time` doesn't begin with a number in [0, 24], error out.
     259             :         // Note: "24:00" is possible in "before 24:00".
     260           0 :         int32_t hour = time[0] - 0x30;
     261           0 :         if (hour < 0 || 9 < hour) {
     262           0 :             errorCode = U_INVALID_FORMAT_ERROR;
     263           0 :             return 0;
     264             :         }
     265           0 :         if (hourLimit == 2) {
     266           0 :             int32_t hourDigit2 = time[1] - 0x30;
     267           0 :             if (hourDigit2 < 0 || 9 < hourDigit2) {
     268           0 :                 errorCode = U_INVALID_FORMAT_ERROR;
     269           0 :                 return 0;
     270             :             }
     271           0 :             hour = hour * 10 + hourDigit2;
     272           0 :             if (hour > 24) {
     273           0 :                 errorCode = U_INVALID_FORMAT_ERROR;
     274           0 :                 return 0;
     275             :             }
     276             :         }
     277             : 
     278           0 :         return hour;
     279             :     }
     280             : };  // struct DayPeriodRulesDataSink
     281             : 
     282           0 : struct DayPeriodRulesCountSink : public ResourceSink {
     283             :     virtual ~DayPeriodRulesCountSink();
     284             : 
     285           0 :     virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
     286           0 :         ResourceTable rules = value.getTable(errorCode);
     287           0 :         if (U_FAILURE(errorCode)) { return; }
     288             : 
     289           0 :         for (int32_t i = 0; rules.getKeyAndValue(i, key, value); ++i) {
     290           0 :             int32_t setNum = DayPeriodRulesDataSink::parseSetNum(key, errorCode);
     291           0 :             if (setNum > data->maxRuleSetNum) {
     292           0 :                 data->maxRuleSetNum = setNum;
     293             :             }
     294             :         }
     295             :     }
     296             : };
     297             : 
     298             : // Out-of-line virtual destructors.
     299           0 : DayPeriodRulesDataSink::~DayPeriodRulesDataSink() {}
     300           0 : DayPeriodRulesCountSink::~DayPeriodRulesCountSink() {}
     301             : 
     302             : namespace {
     303             : 
     304             : UInitOnce initOnce = U_INITONCE_INITIALIZER;
     305             : 
     306           0 : U_CFUNC UBool U_CALLCONV dayPeriodRulesCleanup() {
     307           0 :     delete[] data->rules;
     308           0 :     uhash_close(data->localeToRuleSetNumMap);
     309           0 :     delete data;
     310           0 :     data = NULL;
     311           0 :     return TRUE;
     312             : }
     313             : 
     314             : }  // namespace
     315             : 
     316           0 : void U_CALLCONV DayPeriodRules::load(UErrorCode &errorCode) {
     317           0 :     if (U_FAILURE(errorCode)) {
     318           0 :         return;
     319             :     }
     320             : 
     321           0 :     data = new DayPeriodRulesData();
     322           0 :     data->localeToRuleSetNumMap = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &errorCode);
     323           0 :     LocalUResourceBundlePointer rb_dayPeriods(ures_openDirect(NULL, "dayPeriods", &errorCode));
     324             : 
     325             :     // Get the largest rule set number (so we allocate enough objects).
     326           0 :     DayPeriodRulesCountSink countSink;
     327           0 :     ures_getAllItemsWithFallback(rb_dayPeriods.getAlias(), "rules", countSink, errorCode);
     328             : 
     329             :     // Populate rules.
     330           0 :     DayPeriodRulesDataSink sink;
     331           0 :     ures_getAllItemsWithFallback(rb_dayPeriods.getAlias(), "", sink, errorCode);
     332             : 
     333           0 :     ucln_i18n_registerCleanup(UCLN_I18N_DAYPERIODRULES, dayPeriodRulesCleanup);
     334             : }
     335             : 
     336           0 : const DayPeriodRules *DayPeriodRules::getInstance(const Locale &locale, UErrorCode &errorCode) {
     337           0 :     umtx_initOnce(initOnce, DayPeriodRules::load, errorCode);
     338             : 
     339             :     // If the entire day period rules data doesn't conform to spec (even if the part we want
     340             :     // does), return NULL.
     341           0 :     if(U_FAILURE(errorCode)) { return NULL; }
     342             : 
     343           0 :     const char *localeCode = locale.getName();
     344             :     char name[ULOC_FULLNAME_CAPACITY];
     345             :     char parentName[ULOC_FULLNAME_CAPACITY];
     346             : 
     347           0 :     if (uprv_strlen(localeCode) < ULOC_FULLNAME_CAPACITY) {
     348           0 :         uprv_strcpy(name, localeCode);
     349             : 
     350             :         // Treat empty string as root.
     351           0 :         if (*name == '\0') {
     352           0 :             uprv_strcpy(name, "root");
     353             :         }
     354             :     } else {
     355           0 :         errorCode = U_BUFFER_OVERFLOW_ERROR;
     356           0 :         return NULL;
     357             :     }
     358             : 
     359           0 :     int32_t ruleSetNum = 0;  // NB there is no rule set 0 and 0 is returned upon lookup failure.
     360           0 :     while (*name != '\0') {
     361           0 :         ruleSetNum = uhash_geti(data->localeToRuleSetNumMap, name);
     362           0 :         if (ruleSetNum == 0) {
     363             :             // name and parentName can't be the same pointer, so fill in parent then copy to child.
     364           0 :             uloc_getParent(name, parentName, ULOC_FULLNAME_CAPACITY, &errorCode);
     365           0 :             if (*parentName == '\0') {
     366             :                 // Saves a lookup in the hash table.
     367           0 :                 break;
     368             :             }
     369           0 :             uprv_strcpy(name, parentName);
     370             :         } else {
     371           0 :             break;
     372             :         }
     373             :     }
     374             : 
     375           0 :     if (ruleSetNum <= 0 || data->rules[ruleSetNum].getDayPeriodForHour(0) == DAYPERIOD_UNKNOWN) {
     376             :         // If day period for hour 0 is UNKNOWN then day period for all hours are UNKNOWN.
     377             :         // Data doesn't exist even with fallback.
     378           0 :         return NULL;
     379             :     } else {
     380           0 :         return &data->rules[ruleSetNum];
     381             :     }
     382             : }
     383             : 
     384           0 : DayPeriodRules::DayPeriodRules() : fHasMidnight(FALSE), fHasNoon(FALSE) {
     385           0 :     for (int32_t i = 0; i < 24; ++i) {
     386           0 :         fDayPeriodForHour[i] = DayPeriodRules::DAYPERIOD_UNKNOWN;
     387             :     }
     388           0 : }
     389             : 
     390           0 : double DayPeriodRules::getMidPointForDayPeriod(
     391             :         DayPeriodRules::DayPeriod dayPeriod, UErrorCode &errorCode) const {
     392           0 :     if (U_FAILURE(errorCode)) { return -1; }
     393             : 
     394           0 :     int32_t startHour = getStartHourForDayPeriod(dayPeriod, errorCode);
     395           0 :     int32_t endHour = getEndHourForDayPeriod(dayPeriod, errorCode);
     396             :     // Can't obtain startHour or endHour; bail out.
     397           0 :     if (U_FAILURE(errorCode)) { return -1; }
     398             : 
     399           0 :     double midPoint = (startHour + endHour) / 2.0;
     400             : 
     401           0 :     if (startHour > endHour) {
     402             :         // dayPeriod wraps around midnight. Shift midPoint by 12 hours, in the direction that
     403             :         // lands it in [0, 24).
     404           0 :         midPoint += 12;
     405           0 :         if (midPoint >= 24) {
     406           0 :             midPoint -= 24;
     407             :         }
     408             :     }
     409             : 
     410           0 :     return midPoint;
     411             : }
     412             : 
     413           0 : int32_t DayPeriodRules::getStartHourForDayPeriod(
     414             :         DayPeriodRules::DayPeriod dayPeriod, UErrorCode &errorCode) const {
     415           0 :     if (U_FAILURE(errorCode)) { return -1; }
     416             : 
     417           0 :     if (dayPeriod == DAYPERIOD_MIDNIGHT) { return 0; }
     418           0 :     if (dayPeriod == DAYPERIOD_NOON) { return 12; }
     419             : 
     420           0 :     if (fDayPeriodForHour[0] == dayPeriod && fDayPeriodForHour[23] == dayPeriod) {
     421             :         // dayPeriod wraps around midnight. Start hour is later than end hour.
     422           0 :         for (int32_t i = 22; i >= 1; --i) {
     423           0 :             if (fDayPeriodForHour[i] != dayPeriod) {
     424           0 :                 return (i + 1);
     425             :             }
     426           0 :         }
     427             :     } else {
     428           0 :         for (int32_t i = 0; i <= 23; ++i) {
     429           0 :             if (fDayPeriodForHour[i] == dayPeriod) {
     430           0 :                 return i;
     431             :             }
     432             :         }
     433             :     }
     434             : 
     435             :     // dayPeriod doesn't exist in rule set; set error and exit.
     436           0 :     errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     437           0 :     return -1;
     438             : }
     439             : 
     440           0 : int32_t DayPeriodRules::getEndHourForDayPeriod(
     441             :         DayPeriodRules::DayPeriod dayPeriod, UErrorCode &errorCode) const {
     442           0 :     if (U_FAILURE(errorCode)) { return -1; }
     443             : 
     444           0 :     if (dayPeriod == DAYPERIOD_MIDNIGHT) { return 0; }
     445           0 :     if (dayPeriod == DAYPERIOD_NOON) { return 12; }
     446             : 
     447           0 :     if (fDayPeriodForHour[0] == dayPeriod && fDayPeriodForHour[23] == dayPeriod) {
     448             :         // dayPeriod wraps around midnight. End hour is before start hour.
     449           0 :         for (int32_t i = 1; i <= 22; ++i) {
     450           0 :             if (fDayPeriodForHour[i] != dayPeriod) {
     451             :                 // i o'clock is when a new period starts, therefore when the old period ends.
     452           0 :                 return i;
     453             :             }
     454           0 :         }
     455             :     } else {
     456           0 :         for (int32_t i = 23; i >= 0; --i) {
     457           0 :             if (fDayPeriodForHour[i] == dayPeriod) {
     458           0 :                 return (i + 1);
     459             :             }
     460             :         }
     461             :     }
     462             : 
     463             :     // dayPeriod doesn't exist in rule set; set error and exit.
     464           0 :     errorCode = U_ILLEGAL_ARGUMENT_ERROR;
     465           0 :     return -1;
     466             : }
     467             : 
     468           0 : DayPeriodRules::DayPeriod DayPeriodRules::getDayPeriodFromString(const char *type_str) {
     469           0 :     if (uprv_strcmp(type_str, "midnight") == 0) {
     470           0 :         return DAYPERIOD_MIDNIGHT;
     471           0 :     } else if (uprv_strcmp(type_str, "noon") == 0) {
     472           0 :         return DAYPERIOD_NOON;
     473           0 :     } else if (uprv_strcmp(type_str, "morning1") == 0) {
     474           0 :         return DAYPERIOD_MORNING1;
     475           0 :     } else if (uprv_strcmp(type_str, "afternoon1") == 0) {
     476           0 :         return DAYPERIOD_AFTERNOON1;
     477           0 :     } else if (uprv_strcmp(type_str, "evening1") == 0) {
     478           0 :         return DAYPERIOD_EVENING1;
     479           0 :     } else if (uprv_strcmp(type_str, "night1") == 0) {
     480           0 :         return DAYPERIOD_NIGHT1;
     481           0 :     } else if (uprv_strcmp(type_str, "morning2") == 0) {
     482           0 :         return DAYPERIOD_MORNING2;
     483           0 :     } else if (uprv_strcmp(type_str, "afternoon2") == 0) {
     484           0 :         return DAYPERIOD_AFTERNOON2;
     485           0 :     } else if (uprv_strcmp(type_str, "evening2") == 0) {
     486           0 :         return DAYPERIOD_EVENING2;
     487           0 :     } else if (uprv_strcmp(type_str, "night2") == 0) {
     488           0 :         return DAYPERIOD_NIGHT2;
     489           0 :     } else if (uprv_strcmp(type_str, "am") == 0) {
     490           0 :         return DAYPERIOD_AM;
     491           0 :     } else if (uprv_strcmp(type_str, "pm") == 0) {
     492           0 :         return DAYPERIOD_PM;
     493             :     } else {
     494           0 :         return DAYPERIOD_UNKNOWN;
     495             :     }
     496             : }
     497             : 
     498           0 : void DayPeriodRules::add(int32_t startHour, int32_t limitHour, DayPeriod period) {
     499           0 :     for (int32_t i = startHour; i != limitHour; ++i) {
     500           0 :         if (i == 24) { i = 0; }
     501           0 :         fDayPeriodForHour[i] = period;
     502             :     }
     503           0 : }
     504             : 
     505           0 : UBool DayPeriodRules::allHoursAreSet() {
     506           0 :     for (int32_t i = 0; i < 24; ++i) {
     507           0 :         if (fDayPeriodForHour[i] == DAYPERIOD_UNKNOWN) { return FALSE; }
     508             :     }
     509             : 
     510           0 :     return TRUE;
     511             : }
     512             : 
     513             : 
     514             : 
     515             : U_NAMESPACE_END

Generated by: LCOV version 1.13