static CFRange __CFCalendarGetRangeOfUnit3()

in CoreFoundation/Locale.subproj/CFCalendar.c [2533:2740]


static CFRange __CFCalendarGetRangeOfUnit3(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
    if (!calendar->_cal) {
        __CFCalendarSetupCal(calendar);
        if (!calendar->_cal) {
            return CFRangeMake(kCFNotFound, kCFNotFound);
        }
    }

#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
    switch (biggerUnit) {
        case kCFCalendarUnitCalendar:
        case kCFCalendarUnitTimeZone:
        case kCFCalendarUnitWeekdayOrdinal:
        case kCFCalendarUnitNanosecond:
            return CFRangeMake(kCFNotFound, kCFNotFound);
    }
#pragma GCC diagnostic pop // See 10693376

#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
    switch (smallerUnit) {
    case kCFCalendarUnitWeekday:
        switch (biggerUnit) {
        case kCFCalendarUnitSecond:
        case kCFCalendarUnitMinute:
        case kCFCalendarUnitHour:
        case kCFCalendarUnitDay:
        case kCFCalendarUnitWeekday:
            return CFRangeMake(kCFNotFound, kCFNotFound);
        }
        return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
    case kCFCalendarUnitHour:
        switch (biggerUnit) {
        case kCFCalendarUnitSecond:
        case kCFCalendarUnitMinute:
        case kCFCalendarUnitHour:
            return CFRangeMake(kCFNotFound, kCFNotFound);
        }
        return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
    case kCFCalendarUnitMinute:
        switch (biggerUnit) {
        case kCFCalendarUnitSecond:
        case kCFCalendarUnitMinute:
            return CFRangeMake(kCFNotFound, kCFNotFound);
        }
        return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
    case kCFCalendarUnitSecond:
        switch (biggerUnit) {
        case kCFCalendarUnitSecond:
            return CFRangeMake(kCFNotFound, kCFNotFound);
        }
        return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
    case kCFCalendarUnitNanosecond:
        return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
    }
#pragma GCC diagnostic pop // See 10693376

#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
    switch (biggerUnit) {
    case kCFCalendarUnitEra:
        // assume it cycles through every possible combination in an era
        // at least once; this is a little dodgy for the Japanese calendar
        // but this calculation isn't terribly useful either
        switch (smallerUnit) {
        case kCFCalendarUnitYear: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitYear);
        case kCFCalendarUnitQuarter: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitQuarter);
        case kCFCalendarUnitMonth: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitMonth);
        case kCFCalendarUnitWeek_Deprecated: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitWeek_Deprecated);
        case kCFCalendarUnitWeekOfYear: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitWeekOfYear);
        case kCFCalendarUnitWeekOfMonth: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitWeekOfMonth);
        case kCFCalendarUnitDay: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitDay);
        case kCFCalendarUnitWeekdayOrdinal: {
            CFRange r = CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitDay);
            return CFRangeMake(1, (r.location + r.length - 1 + 6) / 7);
        }
        }
        break;
    case kCFCalendarUnitYear:
        switch (smallerUnit) {
        case kCFCalendarUnitQuarter:
        case kCFCalendarUnitMonth:
        case kCFCalendarUnitWeekOfYear:
        case kCFCalendarUnitWeek_Deprecated: algorithmA: {
            CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
            CFAbsoluteTime start = 0.0;
            CFTimeInterval ti = 0.0;
            Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &start, &ti);
            if (!b) return result;
            CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, biggerUnit, start + 0.1);
            if (kCFNotFound == ord1) return result;
            CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, biggerUnit, start + ti - 0.1);
            if (kCFNotFound == ord2) return result;
            return CFRangeMake(ord1, ord2 + 1 - ord1);
        }
        case kCFCalendarUnitWeekOfMonth:
        case kCFCalendarUnitDay:
        case kCFCalendarUnitWeekdayOrdinal: algorithmB: {
            CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
            CFAbsoluteTime start = 0.0;
            CFTimeInterval ti = 0.0;
            Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &start, &ti);
            if (!b) return result;
            CFIndex counter = 15; // stopgap in case something goes wrong
            CFAbsoluteTime end = start + ti - 1.0;
            CFAbsoluteTime current = start + 1.0;
            do {
                CFAbsoluteTime startM = 0.0;
                CFTimeInterval tiM = 0.0;
                b = CFCalendarGetTimeRangeOfUnit(calendar, kCFCalendarUnitMonth, current, &startM, &tiM);
                if (!b) return result;
                CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, startM + 0.1);
                if (kCFNotFound == ord1) return result;
                CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, startM + tiM - 0.1);
                if (kCFNotFound == ord2) return result;
                if ((kCFNotFound == result.location) || (kCFNotFound == result.length)) {
                    result = CFRangeMake(ord1, ord2 + 1 - ord1);
                } else {
                     CFIndex mn = result.location;
                     if (ord1 < mn) mn = ord1;
                     result.location = mn;
                     result.length += ord2;
                }
                counter--;
                current = startM + tiM + 1.0;
            } while (current < end && 0 < counter);
            return result;
        }
        }
        break;
    case kCFCalendarUnitYearForWeekOfYear:
        switch (smallerUnit) {
        case kCFCalendarUnitQuarter:
        case kCFCalendarUnitMonth:
        case kCFCalendarUnitWeekOfYear:
        case kCFCalendarUnitWeek_Deprecated:
            goto algorithmA; // some of these are going to return (kCFNotFound, kCFNotFound)
        case kCFCalendarUnitWeekOfMonth:
            break;
        case kCFCalendarUnitDay:
        case kCFCalendarUnitWeekdayOrdinal:
            goto algorithmB; // this question is odd to ask
        }
        break;
    case kCFCalendarUnitQuarter:
        switch (smallerUnit) {
        case kCFCalendarUnitMonth:
        case kCFCalendarUnitWeekOfYear:
        case kCFCalendarUnitWeek_Deprecated: algorithmC: {
            CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
            CFAbsoluteTime start = 0.0;
            CFTimeInterval ti = 0.0;
            Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &start, &ti);
            if (!b) return result;
            CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitYear, start + 0.1);
            if (kCFNotFound == ord1) return result;
            CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitYear, start + ti - 0.1);
            if (kCFNotFound == ord2) return result;
            return CFRangeMake(ord1, ord2 + 1 - ord1);
        }
        case kCFCalendarUnitWeekOfMonth:
        case kCFCalendarUnitDay:
        case kCFCalendarUnitWeekdayOrdinal:
            goto algorithmB;
        }
        break;
    case kCFCalendarUnitMonth:
        switch (smallerUnit) {
        case kCFCalendarUnitWeekOfYear:
        case kCFCalendarUnitWeek_Deprecated:
            goto algorithmC;
        case kCFCalendarUnitWeekOfMonth:
        case kCFCalendarUnitDay:
        case kCFCalendarUnitWeekdayOrdinal:
            goto algorithmA;
        }
        break;
    case kCFCalendarUnitWeekOfYear:
        break;
    case kCFCalendarUnitWeekOfMonth:
    case kCFCalendarUnitWeek_Deprecated:
#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
        switch (smallerUnit) {
        case kCFCalendarUnitDay: {
            CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
            CFAbsoluteTime startW = 0.0, startM = 0.0;
            CFTimeInterval tiW = 0.0, tiM = 0.0;
            Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &startW, &tiW);
            if (!b) return result;
            b = CFCalendarGetTimeRangeOfUnit(calendar, kCFCalendarUnitMonth, at, &startM, &tiM);
            if (!b) return result;
            CFAbsoluteTime start = (startW < startM) ? (startM) : (startW);
            CFAbsoluteTime end = (startW + tiW < startM + tiM) ? (startW + tiW) : (startM + tiM);
            CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, start + 0.1);
            if (kCFNotFound == ord1) return result;
            CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, end - 0.1);
            if (kCFNotFound == ord2) return result;
            return CFRangeMake(ord1, ord2 + 1 - ord1);
        }
        }
#pragma GCC diagnostic pop // See 10693376
        break;
    }
#pragma GCC diagnostic pop // See 10693376
    return CFRangeMake(kCFNotFound, kCFNotFound);
}