* Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
* Copyright (C) 2006-2007 Oliver Lupton <oliverlupton@gmail.com>
* Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ * Copyright (C) 2003-2019 Anope Team <team@anope.org>
*
* This file is part of InspIRCd. InspIRCd is free software: you can
* redistribute it and/or modify it under the terms of the GNU General Public
#endif
}
-/** Refactored by Brain, Jun 2009. Much faster with some clever O(1) array
- * lookups and pointer maths.
+/** A lookup table of values for multiplier characters used by
+ * InspIRCd::Duration(). In this lookup table, the indexes for
+ * the ascii values 'm' and 'M' have the value '60', the indexes
+ * for the ascii values 'D' and 'd' have a value of '86400', etc.
*/
-unsigned long InspIRCd::Duration(const std::string &str)
+static const unsigned int duration_multi[] =
{
- unsigned char multiplier = 0;
- long total = 0;
- long times = 1;
- long subtotal = 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 86400, 0, 0, 0, 3600, 0, 0, 0, 0, 60, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 604800, 0, 31557600, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 86400, 0, 0, 0, 3600, 0, 0, 0, 0, 60, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 604800, 0, 31557600, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+bool InspIRCd::Duration(const std::string& str, unsigned long& duration)
+{
+ unsigned long total = 0;
+ unsigned long subtotal = 0;
/* Iterate each item in the string, looking for number or multiplier */
- for (std::string::const_reverse_iterator i = str.rbegin(); i != str.rend(); ++i)
+ for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
{
/* Found a number, queue it onto the current number */
if ((*i >= '0') && (*i <= '9'))
{
- subtotal = subtotal + ((*i - '0') * times);
- times = times * 10;
+ subtotal = (subtotal * 10) + (*i - '0');
}
else
{
* it multiplies the built up number by, multiply the total
* and reset the built up number.
*/
- if (subtotal)
- total += subtotal * duration_multi[multiplier];
+ unsigned int multiplier = duration_multi[static_cast<unsigned char>(*i)];
+ if (multiplier == 0)
+ return false;
+
+ total += subtotal * multiplier;
/* Next subtotal please */
subtotal = 0;
- multiplier = *i;
- times = 1;
}
}
- if (multiplier)
+ /* Any trailing values built up are treated as raw seconds */
+ duration = total + subtotal;
+ return true;
+}
+
+unsigned long InspIRCd::Duration(const std::string& str)
+{
+ unsigned long out = 0;
+ InspIRCd::Duration(str, out);
+ return out;
+}
+
+bool InspIRCd::IsValidDuration(const std::string& duration)
+{
+ for (std::string::const_iterator i = duration.begin(); i != duration.end(); ++i)
{
- total += subtotal * duration_multi[multiplier];
- subtotal = 0;
+ unsigned char c = *i;
+ if (((c >= '0') && (c <= '9')))
+ continue;
+
+ if (!duration_multi[c])
+ return false;
}
- /* Any trailing values built up are treated as raw seconds */
- return total + subtotal;
+ return true;
+}
+
+std::string InspIRCd::DurationString(time_t duration)
+{
+ time_t years = duration / 31536000;
+ time_t weeks = (duration / 604800) % 52;
+ time_t days = (duration / 86400) % 7;
+ time_t hours = (duration / 3600) % 24;
+ time_t minutes = (duration / 60) % 60;
+ time_t seconds = duration % 60;
+
+ std::string ret;
+
+ if (years)
+ ret = ConvToStr(years) + "y";
+ if (weeks)
+ ret += ConvToStr(weeks) + "w";
+ if (days)
+ ret += ConvToStr(days) + "d";
+ if (hours)
+ ret += ConvToStr(hours) + "h";
+ if (minutes)
+ ret += ConvToStr(minutes) + "m";
+ if (seconds)
+ ret += ConvToStr(seconds) + "s";
+
+ return ret;
}
std::string InspIRCd::Format(va_list& vaList, const char* formatString)