text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

namespace TimeHelpers
{
    static std::tm millisToLocal (int64 millis) noexcept
    {
       #if JUCE_WINDOWS && JUCE_MINGW
        auto now = (time_t) (millis / 1000);
        return *localtime (&now);

       #elif JUCE_WINDOWS
        std::tm result;
        millis /= 1000;

        if (_localtime64_s (&result, &millis) != 0)
            zerostruct (result);

        return result;

       #else
        std::tm result;
        auto now = (time_t) (millis / 1000);

        if (localtime_r (&now, &result) == nullptr)
            zerostruct (result);

        return result;
       #endif
    }

    static std::tm millisToUTC (int64 millis) noexcept
    {
       #if JUCE_WINDOWS && JUCE_MINGW
        auto now = (time_t) (millis / 1000);
        return *gmtime (&now);

       #elif JUCE_WINDOWS
        std::tm result;
        millis /= 1000;

        if (_gmtime64_s (&result, &millis) != 0)
            zerostruct (result);

        return result;

       #else
        std::tm result;
        auto now = (time_t) (millis / 1000);

        if (gmtime_r (&now, &result) == nullptr)
            zerostruct (result);

        return result;
       #endif
    }

    static int getUTCOffsetSeconds (const int64 millis) noexcept
    {
        auto utc = millisToUTC (millis);
        utc.tm_isdst = -1;  // Treat this UTC time as local to find the offset

        return (int) ((millis / 1000) - (int64) mktime (&utc));
    }

    static int extendedModulo (const int64 value, const int modulo) noexcept
    {
        return (int) (value >= 0 ? (value % modulo)
                                 : (value - ((value / modulo) + 1) * modulo));
    }

    static inline String formatString (const String& format, const std::tm* const tm)
    {
       #if JUCE_ANDROID
        typedef CharPointer_UTF8  StringType;
       #elif JUCE_WINDOWS
        typedef CharPointer_UTF16 StringType;
       #else
        typedef CharPointer_UTF32 StringType;
       #endif

       #ifdef JUCE_MSVC
        if (tm->tm_year < -1900 || tm->tm_year > 8099)
            return {};   // Visual Studio's library can only handle 0 -> 9999 AD
        #endif

        for (size_t bufferSize = 256; ; bufferSize += 256)
        {
            HeapBlock<StringType::CharType> buffer (bufferSize);

            auto numChars =
                       #if JUCE_ANDROID
                        strftime (buffer, bufferSize - 1, format.toUTF8(), tm);
                       #elif JUCE_WINDOWS
                        wcsftime (buffer, bufferSize - 1, format.toWideCharPointer(), tm);
                       #else
                        wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm);
                       #endif

            if (numChars > 0 || format.isEmpty())
                return String (StringType (buffer),
                               StringType (buffer) + (int) numChars);
        }
    }

    //==============================================================================
    static inline bool isLeapYear (int year) noexcept
    {
        return (year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0));
    }

    static inline int daysFromJan1 (int year, int month) noexcept
    {
        const short dayOfYear[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
                                    0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };

        return dayOfYear [(isLeapYear (year) ? 12 : 0) + month];
    }

    static inline int64 daysFromYear0 (int year) noexcept
    {
        --year;
        return 365 * year + (year / 400) - (year / 100) + (year / 4);
    }

    static inline int64 daysFrom1970 (int year) noexcept
    {
        return daysFromYear0 (year) - daysFromYear0 (1970);
    }

    static inline int64 daysFrom1970 (int year, int month) noexcept
    {
        if (month > 11)
        {
            year += month / 12;
            month %= 12;
        }
        else if (month < 0)
        {
            const int numYears = (11 - month) / 12;
            year -= numYears;
            month += 12 * numYears;
        }

        return daysFrom1970 (year) + daysFromJan1 (year, month);
    }

    // There's no posix function that does a UTC version of mktime,
    // so annoyingly we need to implement this manually..
    static inline int64 mktime_utc (const std::tm& t) noexcept
    {
        return 24 * 3600 * (daysFrom1970 (t.tm_year + 1900, t.tm_mon) + (t.tm_mday - 1))
                + 3600 * t.tm_hour
                + 60 * t.tm_min
                + t.tm_sec;
    }

    static uint32 lastMSCounterValue = 0;
}

//==============================================================================
Time::Time() noexcept  : millisSinceEpoch (0)
{
}

Time::Time (const Time& other) noexcept  : millisSinceEpoch (other.millisSinceEpoch)
{
}

Time::Time (int64 ms) noexcept  : millisSinceEpoch (ms)
{
}

Time::Time (int year, int month, int day,
            int hours, int minutes, int seconds, int milliseconds,
            bool useLocalTime) noexcept
{
    std::tm t;
    t.tm_year   = year - 1900;
    t.tm_mon    = month;
    t.tm_mday   = day;
    t.tm_hour   = hours;
    t.tm_min    = minutes;
    t.tm_sec    = seconds;
    t.tm_isdst  = -1;

    millisSinceEpoch = 1000 * (useLocalTime ? (int64) mktime (&t)
                                            : TimeHelpers::mktime_utc (t))
                         + milliseconds;
}

Time::~Time() noexcept
{
}

Time& Time::operator= (const Time& other) noexcept
{
    millisSinceEpoch = other.millisSinceEpoch;
    return *this;
}

//==============================================================================
int64 Time::currentTimeMillis() noexcept
{
   #if JUCE_WINDOWS && ! JUCE_MINGW
    struct _timeb t;
    _ftime_s (&t);
    return ((int64) t.time) * 1000 + t.millitm;
   #else
    struct timeval tv;
    gettimeofday (&tv, nullptr);
    return ((int64) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
   #endif
}

Time JUCE_CALLTYPE Time::getCurrentTime() noexcept
{
    return Time (currentTimeMillis());
}

//==============================================================================
uint32 juce_millisecondsSinceStartup() noexcept;

uint32 Time::getMillisecondCounter() noexcept
{
    auto now = juce_millisecondsSinceStartup();

    if (now < TimeHelpers::lastMSCounterValue)
    {
        // in multi-threaded apps this might be called concurrently, so
        // make sure that our last counter value only increases and doesn't
        // go backwards..
        if (now < TimeHelpers::lastMSCounterValue - 1000)
            TimeHelpers::lastMSCounterValue = now;
    }
    else
    {
        TimeHelpers::lastMSCounterValue = now;
    }

    return now;
}

uint32 Time::getApproximateMillisecondCounter() noexcept
{
    if (TimeHelpers::lastMSCounterValue == 0)
        getMillisecondCounter();

    return TimeHelpers::lastMSCounterValue;
}

void Time::waitForMillisecondCounter (uint32 targetTime) noexcept
{
    for (;;)
    {
        auto now = getMillisecondCounter();

        if (now >= targetTime)
            break;

        auto toWait = (int) (targetTime - now);

        if (toWait > 2)
        {
            Thread::sleep (jmin (20, toWait >> 1));
        }
        else
        {
            // xxx should consider using mutex_pause on the mac as it apparently
            // makes it seem less like a spinlock and avoids lowering the thread pri.
            for (int i = 10; --i >= 0;)
                Thread::yield();
        }
    }
}

//==============================================================================
double Time::highResolutionTicksToSeconds (const int64 ticks) noexcept
{
    return ticks / (double) getHighResolutionTicksPerSecond();
}

int64 Time::secondsToHighResolutionTicks (const double seconds) noexcept
{
    return (int64) (seconds * (double) getHighResolutionTicksPerSecond());
}

//==============================================================================
String Time::toString (const bool includeDate,
                       const bool includeTime,
                       const bool includeSeconds,
                       const bool use24HourClock) const noexcept
{
    String result;

    if (includeDate)
    {
        result << getDayOfMonth() << ' '
               << getMonthName (true) << ' '
               << getYear();

        if (includeTime)
            result << ' ';
    }

    if (includeTime)
    {
        auto mins = getMinutes();

        result << (use24HourClock ? getHours() : getHoursInAmPmFormat())
               << (mins < 10 ? ":0" : ":") << mins;

        if (includeSeconds)
        {
            auto secs = getSeconds();
            result << (secs < 10 ? ":0" : ":") << secs;
        }

        if (! use24HourClock)
            result << (isAfternoon() ? "pm" : "am");
    }

    return result.trimEnd();
}

String Time::formatted (const String& format) const
{
    std::tm t (TimeHelpers::millisToLocal (millisSinceEpoch));
    return TimeHelpers::formatString (format, &t);
}

//==============================================================================
int Time::getYear() const noexcept          { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_year + 1900; }
int Time::getMonth() const noexcept         { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mon; }
int Time::getDayOfYear() const noexcept     { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_yday; }
int Time::getDayOfMonth() const noexcept    { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mday; }
int Time::getDayOfWeek() const noexcept     { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_wday; }
int Time::getHours() const noexcept         { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_hour; }
int Time::getMinutes() const noexcept       { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_min; }
int Time::getSeconds() const noexcept       { return TimeHelpers::extendedModulo (millisSinceEpoch / 1000, 60); }
int Time::getMilliseconds() const noexcept  { return TimeHelpers::extendedModulo (millisSinceEpoch, 1000); }

int Time::getHoursInAmPmFormat() const noexcept
{
    auto hours = getHours();

    if (hours == 0)  return 12;
    if (hours <= 12) return hours;

    return hours - 12;
}

bool Time::isAfternoon() const noexcept
{
    return getHours() >= 12;
}

bool Time::isDaylightSavingTime() const noexcept
{
    return TimeHelpers::millisToLocal (millisSinceEpoch).tm_isdst != 0;
}

String Time::getTimeZone() const noexcept
{
    String zone[2];

  #if JUCE_WINDOWS
   #if JUCE_MSVC || JUCE_CLANG
    _tzset();

    for (int i = 0; i < 2; ++i)
    {
        char name[128] = { 0 };
        size_t length;
        _get_tzname (&length, name, 127, i);
        zone[i] = name;
    }
   #else
    #warning "Can't find a replacement for tzset on mingw - ideas welcome!"
   #endif
  #else
    tzset();

    auto zonePtr = (const char**) tzname;
    zone[0] = zonePtr[0];
    zone[1] = zonePtr[1];
  #endif

    if (isDaylightSavingTime())
    {
        zone[0] = zone[1];

        if (zone[0].length() > 3
             && zone[0].containsIgnoreCase ("daylight")
             && zone[0].contains ("GMT"))
            zone[0] = "BST";
    }

    return zone[0].substring (0, 3);
}

int Time::getUTCOffsetSeconds() const noexcept
{
    return TimeHelpers::getUTCOffsetSeconds (millisSinceEpoch);
}

String Time::getUTCOffsetString (bool includeSemiColon) const
{
    if (int seconds = getUTCOffsetSeconds())
    {
        const int minutes = seconds / 60;

        return String::formatted (includeSemiColon ? "%+03d:%02d"
                                                   : "%+03d%02d",
                                  minutes / 60,
                                  minutes % 60);
    }

    return "Z";
}

String Time::toISO8601 (bool includeDividerCharacters) const
{
    return String::formatted (includeDividerCharacters ? "%04d-%02d-%02dT%02d:%02d:%06.03f"
                                                       : "%04d%02d%02dT%02d%02d%06.03f",
                              getYear(),
                              getMonth() + 1,
                              getDayOfMonth(),
                              getHours(),
                              getMinutes(),
                              getSeconds() + getMilliseconds() / 1000.0)
            + getUTCOffsetString (includeDividerCharacters);
}

static int parseFixedSizeIntAndSkip (String::CharPointerType& t, int numChars, char charToSkip) noexcept
{
    int n = 0;

    for (int i = numChars; --i >= 0;)
    {
        const int digit = (int) (*t - '0');

        if (! isPositiveAndBelow (digit, 10))
            return -1;

        ++t;
        n = n * 10 + digit;
    }

    if (charToSkip != 0 && *t == (juce_wchar) charToSkip)
        ++t;

    return n;
}

Time Time::fromISO8601 (StringRef iso) noexcept
{
    auto t = iso.text;
    auto year = parseFixedSizeIntAndSkip (t, 4, '-');

    if (year < 0)
        return {};

    auto month = parseFixedSizeIntAndSkip (t, 2, '-');

    if (month < 0)
        return {};

    auto day = parseFixedSizeIntAndSkip (t, 2, 0);

    if (day < 0)
        return {};

    int hours = 0, minutes = 0, milliseconds = 0;

    if (*t == 'T')
    {
        ++t;
        hours = parseFixedSizeIntAndSkip (t, 2, ':');

        if (hours < 0)
            return {};

        minutes = parseFixedSizeIntAndSkip (t, 2, ':');

        if (minutes < 0)
            return {};

        auto seconds = parseFixedSizeIntAndSkip (t, 2, 0);

        if (seconds < 0)
             return {};

        if (*t == '.')
        {
            ++t;
            milliseconds = parseFixedSizeIntAndSkip (t, 3, 0);

            if (milliseconds < 0)
                return {};
        }

        milliseconds += 1000 * seconds;
    }

    auto nextChar = t.getAndAdvance();

    if (nextChar == '-' || nextChar == '+')
    {
        auto offsetHours = parseFixedSizeIntAndSkip (t, 2, ':');

        if (offsetHours < 0)
            return {};

        auto offsetMinutes = parseFixedSizeIntAndSkip (t, 2, 0);

        if (offsetMinutes < 0)
            return {};

        auto offsetMs = (offsetHours * 60 + offsetMinutes) * 60 * 1000;
        milliseconds += nextChar == '-' ? offsetMs : -offsetMs; // NB: this seems backwards but is correct!
    }
    else if (nextChar != 0 && nextChar != 'Z')
    {
        return {};
    }

    return Time (year, month - 1, day, hours, minutes, 0, milliseconds, false);
}

String Time::getMonthName (const bool threeLetterVersion) const
{
    return getMonthName (getMonth(), threeLetterVersion);
}

String Time::getWeekdayName (const bool threeLetterVersion) const
{
    return getWeekdayName (getDayOfWeek(), threeLetterVersion);
}

static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
static const char* const longMonthNames[]  = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };

String Time::getMonthName (int monthNumber, const bool threeLetterVersion)
{
    monthNumber %= 12;

    return TRANS (threeLetterVersion ? shortMonthNames [monthNumber]
                                     : longMonthNames [monthNumber]);
}

String Time::getWeekdayName (int day, const bool threeLetterVersion)
{
    static const char* const shortDayNames[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
    static const char* const longDayNames[]  = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

    day %= 7;

    return TRANS (threeLetterVersion ? shortDayNames [day]
                                     : longDayNames [day]);
}

//==============================================================================
Time& Time::operator+= (RelativeTime delta) noexcept           { millisSinceEpoch += delta.inMilliseconds(); return *this; }
Time& Time::operator-= (RelativeTime delta) noexcept           { millisSinceEpoch -= delta.inMilliseconds(); return *this; }

Time operator+ (Time time, RelativeTime delta) noexcept        { Time t (time); return t += delta; }
Time operator- (Time time, RelativeTime delta) noexcept        { Time t (time); return t -= delta; }
Time operator+ (RelativeTime delta, Time time) noexcept        { Time t (time); return t += delta; }
const RelativeTime operator- (Time time1, Time time2) noexcept { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); }

bool operator== (Time time1, Time time2) noexcept      { return time1.toMilliseconds() == time2.toMilliseconds(); }
bool operator!= (Time time1, Time time2) noexcept      { return time1.toMilliseconds() != time2.toMilliseconds(); }
bool operator<  (Time time1, Time time2) noexcept      { return time1.toMilliseconds() <  time2.toMilliseconds(); }
bool operator>  (Time time1, Time time2) noexcept      { return time1.toMilliseconds() >  time2.toMilliseconds(); }
bool operator<= (Time time1, Time time2) noexcept      { return time1.toMilliseconds() <= time2.toMilliseconds(); }
bool operator>= (Time time1, Time time2) noexcept      { return time1.toMilliseconds() >= time2.toMilliseconds(); }

static int getMonthNumberForCompileDate (const String& m) noexcept
{
    for (int i = 0; i < 12; ++i)
        if (m.equalsIgnoreCase (shortMonthNames[i]))
            return i;

    // If you hit this because your compiler has an unusual __DATE__
    // format, let us know so we can add support for it!
    jassertfalse;
    return 0;
}

Time Time::getCompilationDate()
{
    StringArray dateTokens, timeTokens;

    dateTokens.addTokens (__DATE__, true);
    dateTokens.removeEmptyStrings (true);

    timeTokens.addTokens (__TIME__, ":", StringRef());

    return Time (dateTokens[2].getIntValue(),
                 getMonthNumberForCompileDate (dateTokens[0]),
                 dateTokens[1].getIntValue(),
                 timeTokens[0].getIntValue(),
                 timeTokens[1].getIntValue());
}

//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS

class TimeTests  : public UnitTest
{
public:
    TimeTests() : UnitTest ("Time", "Time") {}

    void runTest() override
    {
        beginTest ("Time");

        Time t = Time::getCurrentTime();
        expect (t > Time());

        Thread::sleep (15);
        expect (Time::getCurrentTime() > t);

        expect (t.getTimeZone().isNotEmpty());
        expect (t.getUTCOffsetString (true)  == "Z" || t.getUTCOffsetString (true).length() == 6);
        expect (t.getUTCOffsetString (false) == "Z" || t.getUTCOffsetString (false).length() == 5);

        expect (Time::fromISO8601 (t.toISO8601 (true)) == t);
        expect (Time::fromISO8601 (t.toISO8601 (false)) == t);

        expect (Time::fromISO8601 ("2016-02-16") == Time (2016, 1, 16, 0, 0, 0, 0, false));
        expect (Time::fromISO8601 ("20160216Z") == Time (2016, 1, 16, 0, 0, 0, 0, false));
        expect (Time::fromISO8601 ("2016-02-16T15:03:57+00:00") == Time (2016, 1, 16, 15, 3, 57, 0, false));
        expect (Time::fromISO8601 ("20160216T150357+0000") == Time (2016, 1, 16, 15, 3, 57, 0, false));
        expect (Time::fromISO8601 ("2016-02-16T15:03:57.999+00:00") == Time (2016, 1, 16, 15, 3, 57, 999, false));
        expect (Time::fromISO8601 ("20160216T150357.999+0000") == Time (2016, 1, 16, 15, 3, 57, 999, false));
        expect (Time::fromISO8601 ("2016-02-16T15:03:57.999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
        expect (Time::fromISO8601 ("20160216T150357.999Z") == Time (2016, 1, 16, 15, 3, 57, 999, false));
        expect (Time::fromISO8601 ("2016-02-16T15:03:57.999-02:30") == Time (2016, 1, 16, 17, 33, 57, 999, false));
        expect (Time::fromISO8601 ("20160216T150357.999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));

        expect (Time (1970,  0,  1,  0,  0,  0, 0, false) == Time (0));
        expect (Time (2106,  1,  7,  6, 28, 15, 0, false) == Time (4294967295000));
        expect (Time (2007, 10,  7,  1,  7, 20, 0, false) == Time (1194397640000));
        expect (Time (2038,  0, 19,  3, 14,  7, 0, false) == Time (2147483647000));
        expect (Time (2016,  2,  7, 11, 20,  8, 0, false) == Time (1457349608000));
        expect (Time (1969, 11, 31, 23, 59, 59, 0, false) == Time (-1000));
        expect (Time (1901, 11, 13, 20, 45, 53, 0, false) == Time (-2147483647000));

        expect (Time (1982, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (1983, 1, 1, 12, 0, 0, 0, true));
        expect (Time (1970, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (1971, 1, 1, 12, 0, 0, 0, true));
        expect (Time (2038, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (2039, 1, 1, 12, 0, 0, 0, true));

        expect (Time (1982, 1, 1, 12, 0, 0, 0, false) + RelativeTime::days (365) == Time (1983, 1, 1, 12, 0, 0, 0, false));
        expect (Time (1970, 1, 1, 12, 0, 0, 0, false) + RelativeTime::days (365) == Time (1971, 1, 1, 12, 0, 0, 0, false));
        expect (Time (2038, 1, 1, 12, 0, 0, 0, false) + RelativeTime::days (365) == Time (2039, 1, 1, 12, 0, 0, 0, false));
    }
};

static TimeTests timeTests;

#endif

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/** A relative measure of time.

    The time is stored as a number of seconds, at double-precision floating
    point accuracy, and may be positive or negative.

    If you need an absolute time, (i.e. a date + time), see the Time class.
*/
class JUCE_API  RelativeTime
{
public:
    //==============================================================================
    /** Creates a RelativeTime.

        @param seconds  the number of seconds, which may be +ve or -ve.
        @see milliseconds, minutes, hours, days, weeks
    */
    explicit RelativeTime (double seconds = 0.0) noexcept;

    /** Copies another relative time. */
    RelativeTime (const RelativeTime& other) noexcept;

    /** Copies another relative time. */
    RelativeTime& operator= (const RelativeTime& other) noexcept;

    /** Destructor. */
    ~RelativeTime() noexcept;

    //==============================================================================
    /** Creates a new RelativeTime object representing a number of milliseconds.
        @see seconds, minutes, hours, days, weeks
    */
    static RelativeTime milliseconds (int milliseconds) noexcept;

    /** Creates a new RelativeTime object representing a number of milliseconds.
        @see seconds, minutes, hours, days, weeks
    */
    static RelativeTime milliseconds (int64 milliseconds) noexcept;

    /** Creates a new RelativeTime object representing a number of seconds.
        @see milliseconds, minutes, hours, days, weeks
    */
    static RelativeTime seconds (double seconds) noexcept;

    /** Creates a new RelativeTime object representing a number of minutes.
        @see milliseconds, hours, days, weeks
    */
    static RelativeTime minutes (double numberOfMinutes) noexcept;

    /** Creates a new RelativeTime object representing a number of hours.
        @see milliseconds, minutes, days, weeks
    */
    static RelativeTime hours (double numberOfHours) noexcept;

    /** Creates a new RelativeTime object representing a number of days.
        @see milliseconds, minutes, hours, weeks
    */
    static RelativeTime days (double numberOfDays) noexcept;

    /** Creates a new RelativeTime object representing a number of weeks.
        @see milliseconds, minutes, hours, days
    */
    static RelativeTime weeks (double numberOfWeeks) noexcept;

    //==============================================================================
    /** Returns the number of milliseconds this time represents.
        @see milliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks
    */
    int64 inMilliseconds() const noexcept;

    /** Returns the number of seconds this time represents.
        @see inMilliseconds, inMinutes, inHours, inDays, inWeeks
    */
    double inSeconds() const noexcept       { return numSeconds; }

    /** Returns the number of minutes this time represents.
        @see inMilliseconds, inSeconds, inHours, inDays, inWeeks
    */
    double inMinutes() const noexcept;

    /** Returns the number of hours this time represents.
        @see inMilliseconds, inSeconds, inMinutes, inDays, inWeeks
    */
    double inHours() const noexcept;

    /** Returns the number of days this time represents.
        @see inMilliseconds, inSeconds, inMinutes, inHours, inWeeks
    */
    double inDays() const noexcept;

    /** Returns the number of weeks this time represents.
        @see inMilliseconds, inSeconds, inMinutes, inHours, inDays
    */
    double inWeeks() const noexcept;

    /** Returns a readable textual description of the time.

        The exact format of the string returned will depend on
        the magnitude of the time - e.g.

        "1 min 4 secs", "1 hr 45 mins", "2 weeks 5 days", "140 ms"

        so that only the two most significant units are printed.

        The returnValueForZeroTime value is the result that is returned if the
        length is zero. Depending on your application you might want to use this
        to return something more relevant like "empty" or "0 secs", etc.

        @see inMilliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks
    */
    String getDescription (const String& returnValueForZeroTime = "0") const;

    //==============================================================================
    /** Adds another RelativeTime to this one. */
    RelativeTime operator+= (RelativeTime timeToAdd) noexcept;
    /** Subtracts another RelativeTime from this one. */
    RelativeTime operator-= (RelativeTime timeToSubtract) noexcept;

    /** Adds a number of seconds to this time. */
    RelativeTime operator+= (double secondsToAdd) noexcept;
    /** Subtracts a number of seconds from this time. */
    RelativeTime operator-= (double secondsToSubtract) noexcept;

private:
    //==============================================================================
    double numSeconds;
};

//==============================================================================
/** Compares two RelativeTimes. */
JUCE_API bool JUCE_CALLTYPE operator== (RelativeTime t1, RelativeTime t2) noexcept;
/** Compares two RelativeTimes. */
JUCE_API bool JUCE_CALLTYPE operator!= (RelativeTime t1, RelativeTime t2) noexcept;
/** Compares two RelativeTimes. */
JUCE_API bool JUCE_CALLTYPE operator>  (RelativeTime t1, RelativeTime t2) noexcept;
/** Compares two RelativeTimes. */
JUCE_API bool JUCE_CALLTYPE operator<  (RelativeTime t1, RelativeTime t2) noexcept;
/** Compares two RelativeTimes. */
JUCE_API bool JUCE_CALLTYPE operator>= (RelativeTime t1, RelativeTime t2) noexcept;
/** Compares two RelativeTimes. */
JUCE_API bool JUCE_CALLTYPE operator<= (RelativeTime t1, RelativeTime t2) noexcept;

//==============================================================================
/** Adds two RelativeTimes together. */
JUCE_API RelativeTime  JUCE_CALLTYPE operator+  (RelativeTime t1, RelativeTime t2) noexcept;
/** Subtracts two RelativeTimes. */
JUCE_API RelativeTime  JUCE_CALLTYPE operator-  (RelativeTime t1, RelativeTime t2) noexcept;

} // namespace juce

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/** A timer for measuring performance of code and dumping the results to a file.

    e.g. @code

        PerformanceCounter pc ("fish", 50, "/temp/myfishlog.txt");

        for (;;)
        {
            pc.start();

            doSomethingFishy();

            pc.stop();
        }
    @endcode

    In this example, the time of each period between calling start/stop will be
    measured and averaged over 50 runs, and the results printed to a file
    every 50 times round the loop.
*/
class JUCE_API  PerformanceCounter
{
public:
    //==============================================================================
    /** Creates a PerformanceCounter object.

        @param counterName      the name used when printing out the statistics
        @param runsPerPrintout  the number of start/stop iterations before calling
                                printStatistics()
        @param loggingFile      a file to dump the results to - if this is File(),
                                the results are just written to the debugger output
    */
    PerformanceCounter (const String& counterName,
                        int runsPerPrintout = 100,
                        const File& loggingFile = File());

    /** Destructor. */
    ~PerformanceCounter();

    //==============================================================================
    /** Starts timing.
        @see stop
    */
    void start() noexcept;

    /** Stops timing and prints out the results.

        The number of iterations before doing a printout of the
        results is set in the constructor.

        @see start
    */
    bool stop();

    /** Dumps the current metrics to the debugger output and to a file.

        As well as using Logger::outputDebugString to print the results,
        this will write then to the file specified in the constructor (if
        this was valid).
    */
    void printStatistics();

    /** Holds the current statistics. */
    struct Statistics
    {
        Statistics() noexcept;

        void clear() noexcept;
        String toString() const;

        void addResult (double elapsed) noexcept;

        String name;
        double averageSeconds;
        double maximumSeconds;
        double minimumSeconds;
        double totalSeconds;
        int64 numRuns;
    };

    /** Returns a copy of the current stats, and resets the internal counter. */
    Statistics getStatisticsAndReset();

private:
    //==============================================================================
    Statistics stats;
    int64 runsPerPrint, startTime;
    File outputFile;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PerformanceCounter)
};

//==============================================================================
/**
    Simple RAII class for measuring the time spent in a scope.

    Example:

    {
        double timeSec;

        {
            ScopedTimeMeasurement m (timeSec);
            doSomething();
        }

        Logger::writeToLog (String ("doSomething() took ") + String (timeSec) + "seconds");
    }

    @param resultInSeconds The result of the measurement will be stored in this variable.
*/
class JUCE_API  ScopedTimeMeasurement
{
public:
    ScopedTimeMeasurement (double& resultInSeconds) noexcept
        : result (resultInSeconds)
    {
        result = 0.0;
    }

    ~ScopedTimeMeasurement()
    {
        static auto scaler = 1.0 / static_cast<double> (Time::getHighResolutionTicksPerSecond());
        result = static_cast<double> (Time::getHighResolutionTicks() - startTimeTicks) * scaler;
    }

private:
    int64 startTimeTicks = Time::getHighResolutionTicks();
    double& result;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScopedTimeMeasurement)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

static void appendToFile (const File& f, const String& s)
{
    if (f.getFullPathName().isNotEmpty())
    {
        FileOutputStream out (f);

        if (! out.failedToOpen())
            out << s << newLine;
    }
}

PerformanceCounter::PerformanceCounter (const String& name, int runsPerPrintout, const File& loggingFile)
    : runsPerPrint (runsPerPrintout), startTime (0), outputFile (loggingFile)
{
    stats.name = name;
    appendToFile (outputFile, "**** Counter for \"" + name + "\" started at: " + Time::getCurrentTime().toString (true, true));
}

PerformanceCounter::~PerformanceCounter()
{
    printStatistics();
}

PerformanceCounter::Statistics::Statistics() noexcept
    : averageSeconds(), maximumSeconds(), minimumSeconds(), totalSeconds(), numRuns()
{
}

void PerformanceCounter::Statistics::clear() noexcept
{
    averageSeconds = maximumSeconds = minimumSeconds = totalSeconds = 0;
    numRuns = 0;
}

void PerformanceCounter::Statistics::addResult (double elapsed) noexcept
{
    if (numRuns == 0)
    {
        maximumSeconds = elapsed;
        minimumSeconds = elapsed;
    }
    else
    {
        maximumSeconds = jmax (maximumSeconds, elapsed);
        minimumSeconds = jmin (minimumSeconds, elapsed);
    }

    ++numRuns;
    totalSeconds += elapsed;
}

static String timeToString (double secs)
{
    return String ((int64) (secs * (secs < 0.01 ? 1000000.0 : 1000.0) + 0.5))
                    + (secs < 0.01 ? " microsecs" : " millisecs");
}

String PerformanceCounter::Statistics::toString() const
{
    MemoryOutputStream s;

    s << "Performance count for \"" << name << "\" over " << numRuns << " run(s)" << newLine
      << "Average = "   << timeToString (averageSeconds)
      << ", minimum = " << timeToString (minimumSeconds)
      << ", maximum = " << timeToString (maximumSeconds)
      << ", total = "   << timeToString (totalSeconds);

    return s.toString();
}

void PerformanceCounter::start() noexcept
{
    startTime = Time::getHighResolutionTicks();
}

bool PerformanceCounter::stop()
{
    stats.addResult (Time::highResolutionTicksToSeconds (Time::getHighResolutionTicks() - startTime));

    if (stats.numRuns < runsPerPrint)
        return false;

    printStatistics();
    return true;
}

void PerformanceCounter::printStatistics()
{
    const String desc (getStatisticsAndReset().toString());

    Logger::outputDebugString (desc);
    appendToFile (outputFile, desc);
}

PerformanceCounter::Statistics PerformanceCounter::getStatisticsAndReset()
{
    Statistics s (stats);
    stats.clear();

    if (s.numRuns > 0)
        s.averageSeconds = s.totalSeconds / s.numRuns;

    return s;
}

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

#if ! JUCE_ANDROID  // We currently don't request runtime permissions on any other platform
                    // than Android, so this file contains a dummy implementation for those.
                    // This may change in the future.

void RuntimePermissions::request (PermissionID, Callback callback)   { callback (true); }
bool RuntimePermissions::isRequired (PermissionID) { return false; }
bool RuntimePermissions::isGranted (PermissionID) { return true; }

#endif

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    A universally unique 128-bit identifier.

    This class generates very random unique numbers. It's vanishingly unlikely
    that two identical UUIDs would ever be created by chance. The values are
    formatted to meet the RFC 4122 version 4 standard.

    The class includes methods for saving the ID as a string or as raw binary data.
*/
class JUCE_API  Uuid
{
public:
    //==============================================================================
    /** Creates a new unique ID, compliant with RFC 4122 version 4. */
    Uuid();

    /** Destructor. */
    ~Uuid() noexcept;

    /** Creates a copy of another UUID. */
    Uuid (const Uuid&) noexcept;

    /** Copies another UUID. */
    Uuid& operator= (const Uuid&) noexcept;

    //==============================================================================
    /** Returns true if the ID is zero. */
    bool isNull() const noexcept;

    /** Returns a null Uuid object. */
    static Uuid null() noexcept;

    bool operator== (const Uuid&) const noexcept;
    bool operator!= (const Uuid&) const noexcept;
    bool operator<  (const Uuid&) const noexcept;
    bool operator>  (const Uuid&) const noexcept;
    bool operator<= (const Uuid&) const noexcept;
    bool operator>= (const Uuid&) const noexcept;

    //==============================================================================
    /** Returns a stringified version of this UUID.

        A Uuid object can later be reconstructed from this string using operator= or
        the constructor that takes a string parameter.

        @returns a 32 character hex string.
    */
    String toString() const;

    /** Returns a stringified version of this UUID, separating it into sections with dashes.
        @returns a string in the format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    */
    String toDashedString() const;

    /** Creates an ID from an encoded string version.
        @see toString
    */
    Uuid (const String& uuidString);

    /** Copies from a stringified UUID.
        The string passed in should be one that was created with the toString() method.
    */
    Uuid& operator= (const String& uuidString);

    //==============================================================================
    /** Returns the time-low section of the UUID. */
    uint32 getTimeLow() const noexcept;
    /** Returns the time-mid section of the UUID. */
    uint16 getTimeMid() const noexcept;
    /** Returns the time-high-and-version section of the UUID. */
    uint16 getTimeHighAndVersion() const noexcept;
    /** Returns the clock-seq-and-reserved section of the UUID. */
    uint8  getClockSeqAndReserved() const noexcept;
    /** Returns the clock-seq-low section of the UUID. */
    uint8  getClockSeqLow() const noexcept;
    /** Returns the node section of the UUID. */
    uint64 getNode() const noexcept;

    //==============================================================================
    /** Returns a pointer to the internal binary representation of the ID.

        This is an array of 16 bytes. To reconstruct a Uuid from its data, use
        the constructor or operator= method that takes an array of uint8s.
    */
    const uint8* getRawData() const noexcept                { return uuid; }

    /** Creates a UUID from a 16-byte array.
        @see getRawData
    */
    Uuid (const uint8* rawData) noexcept;

    /** Sets this UUID from 16-bytes of raw data. */
    Uuid& operator= (const uint8* rawData) noexcept;

private:
    //==============================================================================
    uint8 uuid[16];
    String getHexRegion (int, int) const;
    int compare (Uuid) const noexcept;

    JUCE_LEAK_DETECTOR (Uuid)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

#if JUCE_WINDOWS || DOXYGEN

/**
    Contains some static helper functions for manipulating the MS Windows registry
    (Only available on Windows, of course!)
*/
class JUCE_API  WindowsRegistry
{
public:
    /** These values can be used to specify whether the 32- or 64-bit registry should be used.
        When running on a 32-bit OS, there is no 64-bit registry, so the mode will be ignored.
    */
    enum WoW64Mode
    {
        /** Default handling: 32-bit apps will use the 32-bit registry, and 64-bit apps
            will use the 64-bit registry. */
        WoW64_Default = 0,

        /** Always use the 64-bit registry store. (KEY_WOW64_64KEY). */
        WoW64_64bit  = 0x100,

        /** Always use the 32-bit registry store. (KEY_WOW64_32KEY). */
        WoW64_32bit  = 0x200
    };

    //==============================================================================
    /** Returns a string from the registry.
        The path is a string for the entire path of a value in the registry,
        e.g. "HKEY_CURRENT_USER\Software\foo\bar"
    */
    static String JUCE_CALLTYPE getValue (const String& regValuePath,
                                          const String& defaultValue = String(),
                                          WoW64Mode mode = WoW64_Default);

    /** Reads a binary block from the registry.
        The path is a string for the entire path of a value in the registry,
        e.g. "HKEY_CURRENT_USER\Software\foo\bar"
        @returns a DWORD indicating the type of the key.
    */
    static uint32 JUCE_CALLTYPE getBinaryValue (const String& regValuePath, MemoryBlock& resultData, WoW64Mode mode = WoW64_Default);

    /** Sets a registry value as a string.
        This will take care of creating any groups needed to get to the given registry value.
    */
    static bool JUCE_CALLTYPE setValue (const String& regValuePath, const String& value, WoW64Mode mode = WoW64_Default);

    /** Sets a registry value as a DWORD.
        This will take care of creating any groups needed to get to the given registry value.
    */
    static bool JUCE_CALLTYPE setValue (const String& regValuePath, uint32 value, WoW64Mode mode = WoW64_Default);

    /** Sets a registry value as a QWORD.
        This will take care of creating any groups needed to get to the given registry value.
    */
    static bool JUCE_CALLTYPE setValue (const String& regValuePath, uint64 value, WoW64Mode mode = WoW64_Default);

    /** Sets a registry value as a binary block.
        This will take care of creating any groups needed to get to the given registry value.
    */
    static bool JUCE_CALLTYPE setValue (const String& regValuePath, const MemoryBlock& value, WoW64Mode mode = WoW64_Default);

    /** Returns true if the given value exists in the registry. */
    static bool JUCE_CALLTYPE valueExists (const String& regValuePath, WoW64Mode mode = WoW64_Default);

    /** Returns true if the given key exists in the registry. */
    static bool JUCE_CALLTYPE keyExists (const String& regValuePath, WoW64Mode mode = WoW64_Default);

    /** Deletes a registry value. */
    static bool JUCE_CALLTYPE deleteValue (const String& regValuePath, WoW64Mode mode = WoW64_Default);

    /** Deletes a registry key (which is registry-talk for 'folder'). */
    static bool JUCE_CALLTYPE deleteKey (const String& regKeyPath, WoW64Mode mode = WoW64_Default);

    /** Creates a file association in the registry.

        This lets you set the executable that should be launched by a given file extension.
        @param fileExtension        the file extension to associate, including the
                                    initial dot, e.g. ".txt"
        @param symbolicDescription  a space-free short token to identify the file type
        @param fullDescription      a human-readable description of the file type
        @param targetExecutable     the executable that should be launched
        @param iconResourceNumber   the icon that gets displayed for the file type will be
                                    found by looking up this resource number in the
                                    executable. Pass 0 here to not use an icon
        @param registerForCurrentUserOnly   if false, this will try to register the association
                                    for all users (you might not have permission to do this
                                    unless running in an installer). If true, it will register the
                                    association in HKEY_CURRENT_USER.
        @param mode                 the WoW64 mode to use for choosing the database
    */
    static bool JUCE_CALLTYPE registerFileAssociation (const String& fileExtension,
                                                       const String& symbolicDescription,
                                                       const String& fullDescription,
                                                       const File& targetExecutable,
                                                       int iconResourceNumber,
                                                       bool registerForCurrentUserOnly,
                                                       WoW64Mode mode = WoW64_Default);

    // DEPRECATED: use the other methods with a WoW64Mode parameter of WoW64_64bit instead.
    JUCE_DEPRECATED (static String getValueWow64 (const String&, const String& defaultValue = String()));
    JUCE_DEPRECATED (static bool valueExistsWow64 (const String&));
    JUCE_DEPRECATED (static bool keyExistsWow64 (const String&));

private:
    WindowsRegistry() JUCE_DELETED_FUNCTION;
    JUCE_DECLARE_NON_COPYABLE (WindowsRegistry)
};

#endif

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Represents the 'success' or 'failure' of an operation, and holds an associated
    error message to describe the error when there's a failure.

    E.g.
    @code
    Result myOperation()
    {
        if (doSomeKindOfFoobar())
            return Result::ok();
        else
            return Result::fail ("foobar didn't work!");
    }

    const Result result (myOperation());

    if (result.wasOk())
    {
        ...it's all good...
    }
    else
    {
        warnUserAboutFailure ("The foobar operation failed! Error message was: "
                                + result.getErrorMessage());
    }
    @endcode
*/
class JUCE_API  Result
{
public:
    //==============================================================================
    /** Creates and returns a 'successful' result. */
    static Result ok() noexcept                         { return Result(); }

    /** Creates a 'failure' result.
        If you pass a blank error message in here, a default "Unknown Error" message
        will be used instead.
    */
    static Result fail (const String& errorMessage) noexcept;

    //==============================================================================
    /** Returns true if this result indicates a success. */
    bool wasOk() const noexcept;

    /** Returns true if this result indicates a failure.
        You can use getErrorMessage() to retrieve the error message associated
        with the failure.
    */
    bool failed() const noexcept;

    /** Returns true if this result indicates a success.
        This is equivalent to calling wasOk().
    */
    operator bool() const noexcept;

    /** Returns true if this result indicates a failure.
        This is equivalent to calling failed().
    */
    bool operator!() const noexcept;

    /** Returns the error message that was set when this result was created.
        For a successful result, this will be an empty string;
    */
    const String& getErrorMessage() const noexcept;

    //==============================================================================
    Result (const Result&);
    Result& operator= (const Result&);
    Result (Result&&) noexcept;
    Result& operator= (Result&&) noexcept;

    bool operator== (const Result& other) const noexcept;
    bool operator!= (const Result& other) const noexcept;

private:
    String errorMessage;

    // The default constructor is not for public use!
    // Instead, use Result::ok() or Result::fail()
    Result() noexcept;
    explicit Result (const String&) noexcept;

    // These casts are private to prevent people trying to use the Result object in numeric contexts
    operator int() const;
    operator void*() const;
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Class to handle app runtime permissions for certain functionality on some platforms.

    The use of this class is currently only required if the app should run on
    Android API level 23 and higher.

    On lower API levels, the permissions are specified in the app manifest. On iOS,
    runtime permission requests are handled automatically by the Apple APIs and not
    manually in the app code. On Windows, OS X, and Linux, runtime permissions are not
    used at all. In all these cases, request() will simply call through to the
    callback with no overhead and pass true (making it safe to use on all platforms).

    For example, to enable audio recording on Android in your cross-platform app,
    you could modify your code as follows:

    Old code:

        audioDeviceManager.initialise (2, 2, nullptr, true, String(), nullptr);

    New code:

        RuntimePermissions::request (
            RuntimePermissions::audioRecording,
            [this] (bool wasGranted)
            {
                 if (! wasGranted)
                 {
                     // e.g. display an error or initialise with 0 input channels
                     return;
                 }

                 audioDeviceManager.initialise (2, 2, nullptr, true, String(), nullptr);
            }
        );
*/
class JUCE_API  RuntimePermissions
{
public:
    //==============================================================================
    enum PermissionID
    {
        /** Permission to access the microphone (required on Android).
            You need to request this, for example, to initialise an AudioDeviceManager with
            a non-zero number of input channels, and to open the default audio input device.
        */
        recordAudio = 1,

        /** Permission to scan for and pair to Bluetooth MIDI devices (required on Android).
            You need to request this before calling BluetoothMidiDevicePairingDialogue::open(),
            otherwise no devices will be found.
        */
        bluetoothMidi = 2,

        /** Permission to read from external storage such as SD cards */
        readExternalStorage = 3,

        /** Permission to write to external storage such as SD cards */
        writeExternalStorage = 4
    };

    //==============================================================================
    /** Function type of runtime permission request callbacks. */
    typedef std::function<void (bool)> Callback;

    //==============================================================================
    /** Call this method to request a runtime permission.

        @param permission  The PermissionID of the permission you want to request.

        @param callback    The callback to be called after the request has been granted
                           or denied; the argument passed will be true if the permission
                           has been granted and false otherwise.

        If no runtime request is required or possible to obtain the permission, the
        callback will be called immediately. The argument passed in will be true
        if the permission is granted or no permission is required on this platform,
        and false otherwise.

        If a runtime request is required to obtain the permission, the callback
        will be called asynchronously after the OS has granted or denied the requested
        permission (typically by displaying a dialog box to the user and waiting until
        the user has responded).
    */
    static void request (PermissionID permission, Callback callback);

    /** Returns whether a runtime request is required to obtain the permission
        on the current platform.
    */
    static bool isRequired (PermissionID permission);

    /** Returns true if the app has been already granted this permission, either
        via a previous runtime request or otherwise, or no permission is necessary.

        Note that this can be false even if isRequired returns false. In this case,
        the permission can not be obtained at all at runtime.
    */
    static bool isGranted (PermissionID permission);
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   Permission is granted to use this software under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license/

   Permission to use, copy, modify, and/or distribute this software for any
   purpose with or without fee is hereby granted, provided that the above
   copyright notice and this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
   TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
   OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
   TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
   OF THIS SOFTWARE.

   -----------------------------------------------------------------------------

   To release a closed-source product which uses other parts of JUCE not
   licensed under the ISC terms, commercial licenses are available: visit
   www.juce.com for more information.

  ==============================================================================
*/

namespace std
{
    /**
        This class provides an alternative to std::function that is compatible
        with OS X 10.6 and earlier. This will only be used in OS X versions 10.6
        and earlier and the Projucer live build.
    */

    template <typename>
    class function;

    template <typename Result, typename... Arguments>
    class function<Result (Arguments...)>
    {
    public:
        /** Creates an empty function. */
        function() noexcept {}

        /** Creates an empty function. */
        function (decltype (nullptr)) noexcept {}

        /** Creates a function targetting the provided Functor. */
        template <typename Functor>
        function (Functor f)
        {
            functorHolderHelper = getFunctorStorage (sizeof (FunctorHolder<Functor, Result, Arguments...>));
            new (functorHolderHelper) FunctorHolder<Functor, Result, Arguments...> (f);
        }

        /** Copy constructor. */
        function (function const& other)
        {
            copy (other);
        }

        /** Move constructor */
        function (function&& other)
        {
            move (other);
        }

        /** Destructor. */
        ~function()
        {
            release();
        }

        /** Replaces the contents of this function with the contents of another. */
        function& operator= (function const& other)
        {
            release();
            copy (other);

            return *this;
        }

        /** Moves the contents of another function into this one. */
        function& operator= (function&& other)
        {
            release();
            move (other);

            return *this;
        }

        /** Allows conditional expressions to test if this function is empty. */
        explicit operator bool() const noexcept
        {
            return functorHolderHelper != nullptr;
        }

        /** Swaps the contents of this function with another. After this operation the
            two functions will be pointing at each other's targets. */
        void swap (function& other)
        {
            function<Result (Arguments...)> tmp (*this);
            *this = other;
            other = tmp;
        }

        /** Invokes the target of this function. */
        Result operator() (Arguments... args) const
        {
            return (*functorHolderHelper) (args...);
        }

        bool operator== (decltype (nullptr)) const noexcept     { return (functorHolderHelper == nullptr); }
        bool operator!= (decltype (nullptr)) const noexcept     { return (functorHolderHelper != nullptr); }

    private:
        //==============================================================================
        template <typename ReturnType, typename... Args>
        struct FunctorHolderBase
        {
            virtual ~FunctorHolderBase() {}
            virtual int getSize() const noexcept = 0;
            virtual void copy (void*) const = 0;
            virtual ReturnType operator()(Args...) = 0;
        };

        template <typename Functor, typename ReturnType, typename... Args>
        struct FunctorHolder : FunctorHolderBase<Result, Arguments...>
        {
            FunctorHolder (Functor func) : f (func) {}

            int getSize() const noexcept override final
            {
                return sizeof (*this);
            }

            void copy (void* destination) const override final
            {
                new (destination) FunctorHolder (f);
            }

            ReturnType operator()(Args... args) override final
            {
                return f (args...);
            }

            Functor f;
        };

        FunctorHolderBase<Result, Arguments...>* getFunctorStorage (int size)
        {
            return reinterpret_cast<FunctorHolderBase<Result, Arguments...>*>
                       (size > functorHolderStackSize ? new char [size]
                                                      : &(stackFunctorStorage[0]));
        }

        void copy (function const& other)
        {
            if (other.functorHolderHelper != nullptr)
            {
                functorHolderHelper = getFunctorStorage (other.functorHolderHelper->getSize());
                other.functorHolderHelper->copy (functorHolderHelper);
            }
        }

        void move (function& other)
        {
            if (other.functorHolderHelper != nullptr)
            {
                if (other.functorHolderHelper->getSize() > functorHolderStackSize)
                {
                    functorHolderHelper = other.functorHolderHelper;
                }
                else
                {
                    std::copy (other.stackFunctorStorage, other.stackFunctorStorage + functorHolderStackSize,
                               stackFunctorStorage);
                    functorHolderHelper = reinterpret_cast<FunctorHolderBase<Result, Arguments...>*> (&(stackFunctorStorage[0]));
                }

                other.functorHolderHelper = nullptr;
            }
        }

        void release()
        {
            if (functorHolderHelper != nullptr)
            {
                if (functorHolderHelper->getSize() > functorHolderStackSize)
                    delete[] reinterpret_cast<char*> (functorHolderHelper);
                else
                    functorHolderHelper->~FunctorHolderBase<Result, Arguments...>();

                functorHolderHelper = nullptr;
            }
        }

        static const int functorHolderStackSize = 24;
        char stackFunctorStorage[functorHolderStackSize];

        FunctorHolderBase<Result, Arguments...>* functorHolderHelper = nullptr;
    };
}


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   Permission is granted to use this software under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license/

   Permission to use, copy, modify, and/or distribute this software for any
   purpose with or without fee is hereby granted, provided that the above
   copyright notice and this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
   TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
   OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
   TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
   OF THIS SOFTWARE.

   -----------------------------------------------------------------------------

   To release a closed-source product which uses other parts of JUCE not
   licensed under the ISC terms, commercial licenses are available: visit
   www.juce.com for more information.

  ==============================================================================
*/

namespace juce
{

#if JUCE_UNIT_TESTS

namespace FunctionTestsHelpers
{
    static void incrementArgument (int& x) { x++; }
    static double multiply (double x, double a) noexcept { return a * x; }

    struct BigData
    {
        BigData()
        {
            for (auto i = 0; i < bigDataSize; ++i)
                content[i] = i + 1;
        }

        int sum() const
        {
            int result = 0;
            for (auto i = 0; i < bigDataSize; ++i)
                result += content[i];

            return result;
        }

        static const int bigDataSize = 32,
                         bigDataSum = bigDataSize * (bigDataSize + 1) / 2;
        int content[bigDataSize];
    };

    struct FunctionObject
    {
        FunctionObject() {}

        FunctionObject (const FunctionObject& other)
        {
            bigData = new BigData (*other.bigData);
        }

        int operator()(int i) const { return bigData->sum() + i; }

        ScopedPointer<BigData> bigData { new BigData() };
    };
}

class FunctionTests  : public UnitTest
{
public:
    FunctionTests() : UnitTest ("Function", "Function") {}

    void runTest() override
    {
        FunctionTestsHelpers::BigData bigData;

        {
            beginTest ("Functions");

            std::function<void(int&)> f1 (FunctionTestsHelpers::incrementArgument);

            auto x = 0;
            f1 (x);
            expectEquals (x, 1);

            std::function<double(double, double)> f2 (FunctionTestsHelpers::multiply);
            expectEquals (6.0, f2 (2.0, 3.0));

        }

        {
            beginTest ("Function objects");
            std::function<int(int)> f1 = FunctionTestsHelpers::FunctionObject();
            expectEquals (f1 (5), FunctionTestsHelpers::BigData::bigDataSum + 5);
        }

        {
            beginTest ("Lambdas");

            std::function<int()> fStack ([]() { return 3; });
            expectEquals (fStack(), 3);

            std::function<int()> fHeap ([=]() { return bigData.sum(); });
            expectEquals (fHeap(), FunctionTestsHelpers::BigData::bigDataSum);
        }

        {
            beginTest ("Boolean");

            std::function<void(int&)> f1;

            if (f1)
                expect (false);

            std::function<int()> f2 ([]() { return 3; });

            if (! f2)
                expect (false);
        }

        std::function<int()> fEmpty;

        std::function<int()> fStack ([]() { return 3; });

        std::function<int()> fHeap ([=]() { return bigData.sum(); });

        {
            beginTest ("copy constructor");

            std::function<int()> f1 (fStack);
            expectEquals (f1(), 3);

            std::function<int()> f2 (fHeap);
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            std::function<int()> f3 (fEmpty);
            if (f3)
                expect (false);
        }

        {
            beginTest ("assignment");

            std::function<int()> f1;
            f1 = fStack;
            expectEquals (f1(), 3);

            std::function<int()> f2;
            f2 = fHeap;
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            f1 = fHeap;
            expectEquals (f1(), FunctionTestsHelpers::BigData::bigDataSum);

            f2 = fStack;
            expectEquals (f2(), 3);

            f1 = fEmpty;
            if (f1)
                expect (false);
        }

        {
            beginTest ("move constructor");

            ScopedPointer<std::function<int()>> fStackTmp (new std::function<int()> (fStack));
            std::function<int()> f1 (static_cast<std::function<int()>&&> (*fStackTmp));

            fStackTmp = nullptr;
            expectEquals (f1(), 3);

            ScopedPointer<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));
            std::function<int()> f2 (static_cast<std::function<int()>&&> (*fHeapTmp));
            if (*fHeapTmp)
                expect (false);

            fHeapTmp = nullptr;
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            ScopedPointer<std::function<int()>> fEmptyTmp (new std::function<int()>());
            std::function<int()> f3 (static_cast<std::function<int()>&&> (*fEmptyTmp));
            fEmptyTmp = nullptr;
            if (f3)
                expect (false);
        }

        {
            beginTest ("move assignment");

            std::function<int()> f1 (fHeap);
            ScopedPointer<std::function<int()>> fStackTmp (new std::function<int()> (fStack));
            f1 = static_cast<std::function<int()>&&> (*fStackTmp);

            fStackTmp = nullptr;
            expectEquals (f1(), 3);

            std::function<int()> f2 (fStack);
            ScopedPointer<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));
            f2 = static_cast<std::function<int()>&&> (*fHeapTmp);
            if (*fHeapTmp)
                expect (false);

            fHeapTmp = nullptr;
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            std::function<int()> f3 (fHeap);
            ScopedPointer<std::function<int()>> fEmptyTmp (new std::function<int()>());
            f3 = static_cast<std::function<int()>&&> (*fEmptyTmp);
            fEmptyTmp = nullptr;
            if (f3)
                expect (false);
        }

        {
            beginTest ("nullptr");

            std::function<int()> f1 (nullptr);
            if (f1)
                expect (false);

            std::function<int()> f2 ([]() { return 11; });
            f2 = nullptr;
            if (f2)
                expect (false);
        }

        {
            beginTest ("Swap");

            std::function<int()> f1;
            std::function<int()> f2 (fStack);
            f2.swap (f1);
            expectEquals (f1(), 3);
            if (f2)
                expect (false);

            std::function<int()> f3 (fHeap);
            f3.swap (f1);
            expectEquals (f3(), 3);
            expectEquals (f1(), FunctionTestsHelpers::BigData::bigDataSum);
        }
    }
};

static FunctionTests functionTests;

#endif

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

Uuid::Uuid()
{
    Random r;

    for (size_t i = 0; i < sizeof (uuid); ++i)
        uuid[i] = (uint8) (r.nextInt (256));

    // To make it RFC 4122 compliant, need to force a few bits...
    uuid[6] = (uuid[6] & 0x0f) | 0x40;
    uuid[8] = (uuid[8] & 0x3f) | 0x80;
}

Uuid::~Uuid() noexcept {}

Uuid::Uuid (const Uuid& other) noexcept
{
    memcpy (uuid, other.uuid, sizeof (uuid));
}

Uuid& Uuid::operator= (const Uuid& other) noexcept
{
    memcpy (uuid, other.uuid, sizeof (uuid));
    return *this;
}

bool Uuid::operator== (const Uuid& other) const noexcept    { return memcmp (uuid, other.uuid, sizeof (uuid)) == 0; }
bool Uuid::operator!= (const Uuid& other) const noexcept    { return ! operator== (other); }

bool Uuid::operator<  (const Uuid& other) const noexcept    { return compare (other) < 0; }
bool Uuid::operator>  (const Uuid& other) const noexcept    { return compare (other) > 0; }
bool Uuid::operator<= (const Uuid& other) const noexcept    { return compare (other) <= 0; }
bool Uuid::operator>= (const Uuid& other) const noexcept    { return compare (other) >= 0; }

int Uuid::compare (Uuid other) const noexcept
{
    for (size_t i = 0; i < sizeof (uuid); ++i)
        if (int diff = uuid[i] - (int) other.uuid[i])
            return diff > 0 ? 1 : -1;

    return 0;
}

Uuid Uuid::null() noexcept
{
    return Uuid ((const uint8*) nullptr);
}

bool Uuid::isNull() const noexcept
{
    for (auto i : uuid)
        if (i != 0)
            return false;

    return true;
}

String Uuid::getHexRegion (int start, int length) const
{
    return String::toHexString (uuid + start, length, 0);
}

String Uuid::toString() const
{
    return getHexRegion (0, 16);
}

String Uuid::toDashedString() const
{
    return getHexRegion (0, 4)
            + "-" + getHexRegion (4, 2)
            + "-" + getHexRegion (6, 2)
            + "-" + getHexRegion (8, 2)
            + "-" + getHexRegion (10, 6);
}

Uuid::Uuid (const String& uuidString)
{
    operator= (uuidString);
}

Uuid& Uuid::operator= (const String& uuidString)
{
    MemoryBlock mb;
    mb.loadFromHexString (uuidString);
    mb.ensureSize (sizeof (uuid), true);
    mb.copyTo (uuid, 0, sizeof (uuid));
    return *this;
}

Uuid::Uuid (const uint8* const rawData) noexcept
{
    operator= (rawData);
}

Uuid& Uuid::operator= (const uint8* const rawData) noexcept
{
    if (rawData != nullptr)
        memcpy (uuid, rawData, sizeof (uuid));
    else
        zeromem (uuid, sizeof (uuid));

    return *this;
}

uint32 Uuid::getTimeLow() const noexcept                  { return ByteOrder::bigEndianInt (uuid); }
uint16 Uuid::getTimeMid() const noexcept                  { return ByteOrder::bigEndianShort (uuid + 4); }
uint16 Uuid::getTimeHighAndVersion() const noexcept       { return ByteOrder::bigEndianShort (uuid + 6); }
uint8  Uuid::getClockSeqAndReserved() const noexcept      { return uuid[8]; }
uint8  Uuid::getClockSeqLow() const noexcept              { return uuid[9]; }
uint64 Uuid::getNode() const noexcept                     { return (((uint64) ByteOrder::bigEndianShort (uuid + 10)) << 32) + ByteOrder::bigEndianInt (uuid + 12); }

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

Result::Result() noexcept {}

Result::Result (const String& message) noexcept
    : errorMessage (message)
{
}

Result::Result (const Result& other)
    : errorMessage (other.errorMessage)
{
}

Result& Result::operator= (const Result& other)
{
    errorMessage = other.errorMessage;
    return *this;
}

Result::Result (Result&& other) noexcept
    : errorMessage (static_cast<String&&> (other.errorMessage))
{
}

Result& Result::operator= (Result&& other) noexcept
{
    errorMessage = static_cast<String&&> (other.errorMessage);
    return *this;
}

bool Result::operator== (const Result& other) const noexcept
{
    return errorMessage == other.errorMessage;
}

bool Result::operator!= (const Result& other) const noexcept
{
    return errorMessage != other.errorMessage;
}

Result Result::fail (const String& errorMessage) noexcept
{
    return Result (errorMessage.isEmpty() ? "Unknown Error" : errorMessage);
}

const String& Result::getErrorMessage() const noexcept
{
    return errorMessage;
}

bool Result::wasOk() const noexcept         { return errorMessage.isEmpty(); }
Result::operator bool() const noexcept      { return errorMessage.isEmpty(); }
bool Result::failed() const noexcept        { return errorMessage.isNotEmpty(); }
bool Result::operator!() const noexcept     { return errorMessage.isNotEmpty(); }

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

/*******************************************************************************
 The block below describes the properties of this module, and is read by
 the Projucer to automatically generate project code that uses it.
 For details about the syntax and how to create or use a module, see the
 JUCE Module Format.txt file.

 BEGIN_JUCE_MODULE_DECLARATION

  ID:               juce_opengl
  vendor:           juce
  version:          5.2.0
  name:             JUCE OpenGL classes
  description:      Classes for rendering OpenGL in a JUCE window.
  website:          http://www.juce.com/juce
  license:          GPL/Commercial

  dependencies:     juce_gui_extra
  OSXFrameworks:    OpenGL
  iOSFrameworks:    OpenGLES
  linuxLibs:        GL
  mingwLibs:        opengl32

 END_JUCE_MODULE_DECLARATION

*******************************************************************************/

#pragma once
#define JUCE_OPENGL_H_INCLUDED

#include <juce_gui_extra/juce_gui_extra.h>

#undef JUCE_OPENGL
#define JUCE_OPENGL 1

#if JUCE_IOS || JUCE_ANDROID
 #define JUCE_OPENGL_ES 1
#endif

#if JUCE_WINDOWS
 #ifndef APIENTRY
  #define APIENTRY __stdcall
  #define CLEAR_TEMP_APIENTRY 1
 #endif
 #ifndef WINGDIAPI
  #define WINGDIAPI __declspec(dllimport)
  #define CLEAR_TEMP_WINGDIAPI 1
 #endif

 #if JUCE_MINGW
  #include <GL/gl.h>
 #else
  #include <gl/GL.h>
 #endif

 #ifdef CLEAR_TEMP_WINGDIAPI
  #undef WINGDIAPI
  #undef CLEAR_TEMP_WINGDIAPI
 #endif
 #ifdef CLEAR_TEMP_APIENTRY
  #undef APIENTRY
  #undef CLEAR_TEMP_APIENTRY
 #endif
#elif JUCE_LINUX
 #include <GL/gl.h>
 #undef KeyPress
#elif JUCE_IOS
 #if defined (__IPHONE_7_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
  #include <OpenGLES/ES3/gl.h>
 #else
  #include <OpenGLES/ES2/gl.h>
 #endif
#elif JUCE_MAC
 #if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7)
  #define JUCE_OPENGL3 1
  #include <OpenGL/gl3.h>
  #include <OpenGL/gl3ext.h>
 #else
  #include <OpenGL/gl.h>
  #include <OpenGL/glext.h>
 #endif
#elif JUCE_ANDROID
 #include <android/native_window.h>
 #include <android/native_window_jni.h>
 #if JUCE_ANDROID_GL_ES_VERSION_3_0
  #define JUCE_OPENGL3 1
  #include <GLES3/gl3.h>
 #else
  #include <GLES2/gl2.h>
 #endif
 #include <EGL/egl.h>
#endif

#if GL_ES_VERSION_3_0
 #define JUCE_OPENGL3 1
#endif

//==============================================================================
/** This macro is a helper for use in GLSL shader code which needs to compile on both OpenGL 2.1 and OpenGL 3.0.
    It's mandatory in OpenGL 3.0 to specify the GLSL version.
*/
#if JUCE_OPENGL3
 #if JUCE_OPENGL_ES
  #define JUCE_GLSL_VERSION "#version 300 es"
 #else
  #define JUCE_GLSL_VERSION "#version 150"
 #endif
#else
 #define JUCE_GLSL_VERSION ""
#endif

//==============================================================================
#if JUCE_OPENGL_ES || defined (DOXYGEN)
 /** This macro is a helper for use in GLSL shader code which needs to compile on both GLES and desktop GL.
     Since it's mandatory in GLES to mark a variable with a precision, but the keywords don't exist in normal GLSL,
     these macros define the various precision keywords only on GLES.
 */
 #define JUCE_MEDIUMP  "mediump"

 /** This macro is a helper for use in GLSL shader code which needs to compile on both GLES and desktop GL.
     Since it's mandatory in GLES to mark a variable with a precision, but the keywords don't exist in normal GLSL,
     these macros define the various precision keywords only on GLES.
 */
 #define JUCE_HIGHP    "highp"

 /** This macro is a helper for use in GLSL shader code which needs to compile on both GLES and desktop GL.
     Since it's mandatory in GLES to mark a variable with a precision, but the keywords don't exist in normal GLSL,
     these macros define the various precision keywords only on GLES.
 */
 #define JUCE_LOWP     "lowp"
#else
 #define JUCE_MEDIUMP
 #define JUCE_HIGHP
 #define JUCE_LOWP
#endif

//==============================================================================
namespace juce
{
    class OpenGLTexture;
    class OpenGLFrameBuffer;
    class OpenGLShaderProgram;
}

#include "geometry/juce_Vector3D.h"
#include "geometry/juce_Matrix3D.h"
#include "geometry/juce_Quaternion.h"
#include "geometry/juce_Draggable3DOrientation.h"
#include "native/juce_MissingGLDefinitions.h"
#include "opengl/juce_OpenGLHelpers.h"
#include "opengl/juce_OpenGLPixelFormat.h"
#include "native/juce_OpenGLExtensions.h"
#include "opengl/juce_OpenGLRenderer.h"
#include "opengl/juce_OpenGLContext.h"
#include "opengl/juce_OpenGLFrameBuffer.h"
#include "opengl/juce_OpenGLGraphicsContext.h"
#include "opengl/juce_OpenGLImage.h"
#include "opengl/juce_OpenGLShaderProgram.h"
#include "opengl/juce_OpenGLTexture.h"
#include "utils/juce_OpenGLAppComponent.h"


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

#include "juce_opengl.cpp"


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

#ifdef JUCE_OPENGL_H_INCLUDED
 /* When you add this cpp file to your project, you mustn't include it in a file where you've
    already included any other headers - just put it inside a file on its own, possibly with your config
    flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
    header files that the compiler may be using.
 */
 #error "Incorrect use of JUCE cpp file"
#endif

#define JUCE_CORE_INCLUDE_OBJC_HELPERS 1
#define JUCE_CORE_INCLUDE_JNI_HELPERS 1
#define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1
#define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1

#include "juce_opengl.h"

//==============================================================================
#if JUCE_IOS
 #import <QuartzCore/QuartzCore.h>

//==============================================================================
#elif JUCE_WINDOWS
 #include <windowsx.h>

 #if JUCE_MSVC && ! JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
  #pragma comment(lib, "OpenGL32.Lib")
 #endif

//==============================================================================
#elif JUCE_LINUX
 /* Got an include error here?

    If you want to install OpenGL support, the packages to get are "mesa-common-dev"
    and "freeglut3-dev".
 */
 #include <GL/glx.h>

//==============================================================================
#elif JUCE_MAC
 #include <OpenGL/CGLCurrent.h> // These are both just needed with the 10.5 SDK
 #include <OpenGL/OpenGL.h>

//==============================================================================
#elif JUCE_ANDROID
 #ifndef GL_GLEXT_PROTOTYPES
  #define GL_GLEXT_PROTOTYPES 1
 #endif

 #if JUCE_ANDROID_GL_ES_VERSION_3_0
  #include <GLES3/gl3.h>

  // workaround for a bug in SDK 18 and 19
  // see: https://stackoverflow.com/questions/31003863/gles-3-0-including-gl2ext-h
  #define __gl2_h_
  #include <GLES2/gl2ext.h>
 #else
  #include <GLES2/gl2.h>
 #endif
#endif

//==============================================================================
namespace juce
{

void OpenGLExtensionFunctions::initialise()
{
   #if JUCE_WINDOWS || JUCE_LINUX
    #define JUCE_INIT_GL_FUNCTION(name, returnType, params, callparams) \
        name = (type_ ## name) OpenGLHelpers::getExtensionFunction (#name);

    JUCE_GL_BASE_FUNCTIONS (JUCE_INIT_GL_FUNCTION)
    #undef JUCE_INIT_GL_FUNCTION

    #define JUCE_INIT_GL_FUNCTION(name, returnType, params, callparams) \
        name = (type_ ## name) OpenGLHelpers::getExtensionFunction (#name); \
        if (name == nullptr) \
            name = (type_ ## name) OpenGLHelpers::getExtensionFunction (JUCE_STRINGIFY (name ## EXT));

    JUCE_GL_EXTENSION_FUNCTIONS (JUCE_INIT_GL_FUNCTION)
    #if JUCE_OPENGL3
     JUCE_GL_VERTEXBUFFER_FUNCTIONS (JUCE_INIT_GL_FUNCTION)
    #endif

    #undef JUCE_INIT_GL_FUNCTION
   #endif
}

#if JUCE_OPENGL_ES
 #define JUCE_DECLARE_GL_FUNCTION(name, returnType, params, callparams) \
    returnType OpenGLExtensionFunctions::name params noexcept { return ::name callparams; }

 JUCE_GL_BASE_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION)
 JUCE_GL_EXTENSION_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION)
#if JUCE_OPENGL3
 JUCE_GL_VERTEXBUFFER_FUNCTIONS (JUCE_DECLARE_GL_FUNCTION)
#endif

 #undef JUCE_DECLARE_GL_FUNCTION
#endif

#undef JUCE_GL_EXTENSION_FUNCTIONS

#if JUCE_DEBUG && ! defined (JUCE_CHECK_OPENGL_ERROR)
static const char* getGLErrorMessage (const GLenum e) noexcept
{
    switch (e)
    {
        case GL_INVALID_ENUM:                   return "GL_INVALID_ENUM";
        case GL_INVALID_VALUE:                  return "GL_INVALID_VALUE";
        case GL_INVALID_OPERATION:              return "GL_INVALID_OPERATION";
        case GL_OUT_OF_MEMORY:                  return "GL_OUT_OF_MEMORY";
       #ifdef GL_STACK_OVERFLOW
        case GL_STACK_OVERFLOW:                 return "GL_STACK_OVERFLOW";
       #endif
       #ifdef GL_STACK_UNDERFLOW
        case GL_STACK_UNDERFLOW:                return "GL_STACK_UNDERFLOW";
       #endif
       #ifdef GL_INVALID_FRAMEBUFFER_OPERATION
        case GL_INVALID_FRAMEBUFFER_OPERATION:  return "GL_INVALID_FRAMEBUFFER_OPERATION";
       #endif
        default: break;
    }

    return "Unknown error";
}

#if JUCE_MAC || JUCE_IOS

 #ifndef JUCE_IOS_MAC_VIEW
  #if JUCE_IOS
   #define JUCE_IOS_MAC_VIEW    UIView
   #define JUCE_IOS_MAC_WINDOW  UIWindow
  #else
   #define JUCE_IOS_MAC_VIEW    NSView
   #define JUCE_IOS_MAC_WINDOW  NSWindow
  #endif
 #endif

#endif

static bool checkPeerIsValid (OpenGLContext* context)
{
    jassert (context != nullptr);

    if (context != nullptr)
    {
        if (auto* comp = context->getTargetComponent())
        {
            if (auto* peer = comp->getPeer())
            {
               #if JUCE_MAC || JUCE_IOS
                if (auto* nsView = (JUCE_IOS_MAC_VIEW*) peer->getNativeHandle())
                {
                    if (auto* nsWindow = [nsView window])
                    {
                       #if JUCE_MAC
                        return ([nsWindow isVisible]
                                  && (! [nsWindow hidesOnDeactivate] || [NSApp isActive]));
                       #else
                        ignoreUnused (nsWindow);
                        return true;
                       #endif
                    }
                }
               #else
                ignoreUnused (peer);
                return true;
               #endif
            }
        }
    }

    return false;
}

static void checkGLError (const char* file, const int line)
{
    for (;;)
    {
        const GLenum e = glGetError();

        if (e == GL_NO_ERROR)
            break;

        // if the peer is not valid then ignore errors
        if (! checkPeerIsValid (OpenGLContext::getCurrentContext()))
            continue;

        DBG ("***** " << getGLErrorMessage (e) << "  at " << file << " : " << line);
        jassertfalse;
    }
}

 #define JUCE_CHECK_OPENGL_ERROR checkGLError (__FILE__, __LINE__);
#else
 #define JUCE_CHECK_OPENGL_ERROR ;
#endif

static void clearGLError() noexcept
{
    while (glGetError() != GL_NO_ERROR) {}
}

struct OpenGLTargetSaver
{
    OpenGLTargetSaver (const OpenGLContext& c) noexcept
        : context (c), oldFramebuffer (OpenGLFrameBuffer::getCurrentFrameBufferTarget())
    {
        glGetIntegerv (GL_VIEWPORT, oldViewport);
    }

    ~OpenGLTargetSaver() noexcept
    {
        context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, oldFramebuffer);
        glViewport (oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
    }

private:
    const OpenGLContext& context;
    GLuint oldFramebuffer;
    GLint oldViewport[4];

    OpenGLTargetSaver& operator= (const OpenGLTargetSaver&);
};

} // namespace juce

//==============================================================================
#include "opengl/juce_OpenGLFrameBuffer.cpp"
#include "opengl/juce_OpenGLGraphicsContext.cpp"
#include "opengl/juce_OpenGLHelpers.cpp"
#include "opengl/juce_OpenGLImage.cpp"
#include "opengl/juce_OpenGLPixelFormat.cpp"
#include "opengl/juce_OpenGLShaderProgram.cpp"
#include "opengl/juce_OpenGLTexture.cpp"

//==============================================================================
#if JUCE_MAC || JUCE_IOS

 #if JUCE_CLANG
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wundeclared-selector"
 #endif

 #if JUCE_MAC
  #include "native/juce_OpenGL_osx.h"
 #else
  #include "native/juce_OpenGL_ios.h"
 #endif

 #if JUCE_CLANG
  #pragma clang diagnostic pop
 #endif

#elif JUCE_WINDOWS
 #include "native/juce_OpenGL_win32.h"

#elif JUCE_LINUX
 #include "native/juce_OpenGL_linux_X11.h"

#elif JUCE_ANDROID
 #include "native/juce_OpenGL_android.h"

#endif

#include "opengl/juce_OpenGLContext.cpp"
#include "utils/juce_OpenGLAppComponent.cpp"