summaryrefslogtreecommitdiffstats
path: root/src/ptimec.hh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ptimec.hh263
1 files changed, 218 insertions, 45 deletions
diff --git a/src/ptimec.hh b/src/ptimec.hh
index 9db6b0c..527b33d 100644
--- a/src/ptimec.hh
+++ b/src/ptimec.hh
@@ -202,11 +202,6 @@ ftime_a(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
}
inline void
-ftime_Z(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
-{
-}
-
-inline void
ftime_b(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
{
switch (tm.et_tm.tm_mon) {
@@ -287,10 +282,13 @@ ptime_S(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
}
dst->et_tm.tm_sec
= (str[off_inout] - '0') * 10 + (str[off_inout + 1] - '0');
+ if (dst->et_tm.tm_sec < 0 || dst->et_tm.tm_sec >= 60) {
+ return false;
+ }
dst->et_flags |= ETF_SECOND_SET;
});
- return (dst->et_tm.tm_sec >= 0 && dst->et_tm.tm_sec <= 59);
+ return true;
}
inline void
@@ -323,7 +321,7 @@ ptime_s(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
- | ETF_EPOCH_TIME;
+ | ETF_EPOCH_TIME | ETF_ZONE_SET;
return (epoch > 0);
}
@@ -381,7 +379,7 @@ ptime_q(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
| ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
- | ETF_EPOCH_TIME;
+ | ETF_EPOCH_TIME | ETF_ZONE_SET;
return (epoch > 0);
}
@@ -398,20 +396,42 @@ ftime_q(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
inline bool
ptime_L(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
{
+ auto avail = len - off_inout;
int ms = 0;
- PTIME_CONSUME(3, {
- char c0 = str[off_inout];
- char c1 = str[off_inout + 1];
- char c2 = str[off_inout + 2];
- if (!isdigit(c0) || !isdigit(c1) || !isdigit(c2)) {
- return false;
- }
- ms = ((str[off_inout] - '0') * 100 + (str[off_inout + 1] - '0') * 10
- + (str[off_inout + 2] - '0'));
- });
+ if (avail >= 3 && isdigit(str[off_inout + 2])) {
+ PTIME_CONSUME(3, {
+ char c0 = str[off_inout];
+ char c1 = str[off_inout + 1];
+ char c2 = str[off_inout + 2];
+ if (!isdigit(c0) || !isdigit(c1) || !isdigit(c2)) {
+ return false;
+ }
+ ms = ((str[off_inout] - '0') * 100 + (str[off_inout + 1] - '0') * 10
+ + (str[off_inout + 2] - '0'));
+ });
+ } else if (avail >= 2 && isdigit(str[off_inout + 1])) {
+ PTIME_CONSUME(2, {
+ char c0 = str[off_inout];
+ char c1 = str[off_inout + 1];
+ if (!isdigit(c0) || !isdigit(c1)) {
+ return false;
+ }
+ ms = ((str[off_inout] - '0') * 100
+ + (str[off_inout + 1] - '0') * 10);
+ });
+ } else {
+ PTIME_CONSUME(1, {
+ char c0 = str[off_inout];
+ if (!isdigit(c0)) {
+ return false;
+ }
+ ms = (str[off_inout] - '0') * 100;
+ });
+ }
if ((ms >= 0 && ms <= 999)) {
+ dst->et_flags |= ETF_MILLIS_SET;
dst->et_nsec = ms * 1000000;
return true;
}
@@ -457,8 +477,14 @@ ptime_H(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
if (str[off_inout + 1] > '9') {
return false;
}
- dst->et_tm.tm_hour
- = (str[off_inout] - '0') * 10 + (str[off_inout + 1] - '0');
+ if (isdigit(str[off_inout])) {
+ dst->et_tm.tm_hour = (str[off_inout] - '0') * 10;
+ } else if (str[off_inout] == ' ') {
+ dst->et_tm.tm_hour = 0;
+ } else {
+ return false;
+ }
+ dst->et_tm.tm_hour += (str[off_inout + 1] - '0');
dst->et_flags |= ETF_HOUR_SET;
});
@@ -493,8 +519,9 @@ ptime_i(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
- | ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
- | ETF_EPOCH_TIME;
+ | ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MILLIS_SET
+ | ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET
+ | ETF_SUB_NOT_IN_FORMAT;
return (epoch_ms > 0);
}
@@ -530,8 +557,9 @@ ptime_6(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
secs2tm(epoch, &dst->et_tm);
dst->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
- | ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
- | ETF_EPOCH_TIME;
+ | ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MICROS_SET
+ | ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET
+ | ETF_SUB_NOT_IN_FORMAT | ETF_Z_FOR_UTC;
return (epoch_us > 0);
}
@@ -553,8 +581,14 @@ ptime_I(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
if (str[off_inout + 1] > '9') {
return false;
}
- dst->et_tm.tm_hour
- = (str[off_inout] - '0') * 10 + (str[off_inout + 1] - '0');
+ if (isdigit(str[off_inout])) {
+ dst->et_tm.tm_hour = (str[off_inout] - '0') * 10;
+ } else if (str[off_inout] == ' ') {
+ dst->et_tm.tm_hour = 0;
+ } else {
+ return false;
+ }
+ dst->et_tm.tm_hour += (str[off_inout + 1] - '0');
if (dst->et_tm.tm_hour < 1 || dst->et_tm.tm_hour > 12) {
return false;
@@ -725,7 +759,7 @@ ptime_l(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
dst->et_tm.tm_hour = 0;
- if ((off_inout + 1) > len) {
+ if ((off_inout + 1) >= len) {
return false;
}
@@ -734,7 +768,7 @@ ptime_l(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
off_inout += 1;
}
- if ((off_inout + 1) > len) {
+ if ((off_inout + 1) >= len) {
off_inout = orig_off;
return false;
}
@@ -747,7 +781,13 @@ ptime_l(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
dst->et_tm.tm_hour = str[off_inout] - '0';
off_inout += 1;
+ if (!consumed_space && (off_inout + 1) >= len) {
+ off_inout = orig_off;
+ return false;
+ }
+
if (consumed_space || str[off_inout] < '0' || str[off_inout] > '9') {
+ dst->et_flags |= ETF_HOUR_SET;
return true;
}
@@ -756,11 +796,10 @@ ptime_l(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
off_inout += 1;
if (dst->et_tm.tm_hour >= 0 && dst->et_tm.tm_hour <= 23) {
+ dst->et_flags |= ETF_HOUR_SET;
return true;
}
- dst->et_flags |= ETF_HOUR_SET;
-
off_inout = orig_off;
return false;
}
@@ -880,8 +919,71 @@ ftime_y(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
}
inline bool
+ptime_Z_upto(struct exttm* dst,
+ const char* str,
+ off_t& off_inout,
+ ssize_t len,
+ char term)
+{
+ auto avail = len - off_inout;
+
+ if (avail >= 3 && str[off_inout + 0] == 'U' && str[off_inout + 1] == 'T'
+ && str[off_inout + 2] == 'C')
+ {
+ PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_UTC; });
+ dst->et_gmtoff = 0;
+ return true;
+ }
+ if (avail >= 3 && str[off_inout + 0] == 'G' && str[off_inout + 1] == 'M'
+ && str[off_inout + 2] == 'T')
+ {
+ PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_GMT; });
+ dst->et_gmtoff = 0;
+ return true;
+ }
+
+ return ptime_upto(term, str, off_inout, len);
+}
+
+inline bool
+ptime_Z_upto_end(struct exttm* dst,
+ const char* str,
+ off_t& off_inout,
+ ssize_t len)
+{
+ auto avail = len - off_inout;
+
+ if (avail >= 3 && str[off_inout + 0] == 'U' && str[off_inout + 1] == 'T'
+ && str[off_inout + 2] == 'C')
+ {
+ PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_UTC; });
+ dst->et_gmtoff = 0;
+ return true;
+ }
+ if (avail >= 3 && str[off_inout + 0] == 'G' && str[off_inout + 1] == 'M'
+ && str[off_inout + 2] == 'T')
+ {
+ PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_GMT; });
+ dst->et_gmtoff = 0;
+ return true;
+ }
+
+ return ptime_upto_end(str, off_inout, len);
+}
+
+inline bool
ptime_z(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
{
+ if (off_inout + 1 <= len && str[off_inout] == 'Z') {
+ off_inout += 1;
+ dst->et_flags |= ETF_ZONE_SET | ETF_Z_FOR_UTC;
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ dst->et_tm.tm_gmtoff = 0;
+#endif
+ dst->et_gmtoff = 0;
+ return true;
+ }
+
int consume_amount = 5;
if ((off_inout + 6) <= len && str[off_inout + 3] == ':') {
@@ -907,6 +1009,10 @@ ptime_z(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
mins = ((str[off_inout + skip_colon + 3] - '0') * 10
+ (str[off_inout + skip_colon + 4] - '0') * 1)
* 60;
+ if (skip_colon) {
+ dst->et_flags |= ETF_Z_COLON;
+ }
+ dst->et_flags |= ETF_ZONE_SET;
dst->et_gmtoff = sign * (hours + mins);
#ifdef HAVE_STRUCT_TM_TM_ZONE
dst->et_tm.tm_gmtoff = sign * (hours + mins);
@@ -919,6 +1025,15 @@ ptime_z(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
inline void
ftime_z(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
{
+ if (!(tm.et_flags & ETF_ZONE_SET)) {
+ return;
+ }
+
+ if (tm.et_gmtoff == 0 && tm.et_flags & ETF_Z_FOR_UTC) {
+ PTIME_APPEND('Z');
+ return;
+ }
+
long gmtoff = std::abs(tm.et_gmtoff) / 60;
if (tm.et_gmtoff < 0) {
@@ -932,27 +1047,82 @@ ftime_z(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
PTIME_APPEND('0' + ((hours / 10) % 10));
PTIME_APPEND('0' + ((hours / 1) % 10));
+ if (tm.et_flags & ETF_Z_COLON) {
+ PTIME_APPEND(':');
+ }
PTIME_APPEND('0' + ((mins / 10) % 10));
PTIME_APPEND('0' + ((mins / 1) % 10));
}
+inline void
+ftime_Z(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
+{
+ if (tm.et_flags & ETF_Z_IS_UTC) {
+ PTIME_APPEND('U');
+ PTIME_APPEND('T');
+ PTIME_APPEND('C');
+ } else if (tm.et_flags & ETF_Z_IS_GMT) {
+ PTIME_APPEND('G');
+ PTIME_APPEND('M');
+ PTIME_APPEND('T');
+ } else if (tm.et_flags & ETF_ZONE_SET) {
+ ftime_z(dst, off_inout, len, tm);
+ }
+}
+
inline bool
ptime_f(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
{
- PTIME_CONSUME(6, {
- for (int lpc = 0; lpc < 6; lpc++) {
- if (str[off_inout + lpc] < '0' || str[off_inout + lpc] > '9') {
- return false;
+ auto avail = len - off_inout;
+
+ if (avail >= 6 && isdigit(str[off_inout + 4])
+ && isdigit(str[off_inout + 5]))
+ {
+ PTIME_CONSUME(6, {
+ for (int lpc = 0; lpc < 6; lpc++) {
+ if (str[off_inout + lpc] < '0' || str[off_inout + lpc] > '9') {
+ return false;
+ }
}
- }
- dst->et_nsec = ((str[off_inout + 0] - '0') * 100000
- + (str[off_inout + 1] - '0') * 10000
- + (str[off_inout + 2] - '0') * 1000
- + (str[off_inout + 3] - '0') * 100
- + (str[off_inout + 4] - '0') * 10
- + (str[off_inout + 5] - '0') * 1)
- * 1000;
- });
+ dst->et_flags |= ETF_MICROS_SET;
+ dst->et_nsec = ((str[off_inout + 0] - '0') * 100000
+ + (str[off_inout + 1] - '0') * 10000
+ + (str[off_inout + 2] - '0') * 1000
+ + (str[off_inout + 3] - '0') * 100
+ + (str[off_inout + 4] - '0') * 10
+ + (str[off_inout + 5] - '0') * 1)
+ * 1000;
+ });
+ } else if (avail >= 5 && isdigit(str[off_inout + 4])) {
+ PTIME_CONSUME(5, {
+ for (int lpc = 0; lpc < 5; lpc++) {
+ if (str[off_inout + lpc] < '0' || str[off_inout + lpc] > '9') {
+ return false;
+ }
+ }
+ dst->et_flags |= ETF_MICROS_SET;
+ dst->et_nsec = ((str[off_inout + 0] - '0') * 100000
+ + (str[off_inout + 1] - '0') * 10000
+ + (str[off_inout + 2] - '0') * 1000
+ + (str[off_inout + 3] - '0') * 100
+ + (str[off_inout + 4] - '0') * 10)
+ * 1000;
+ });
+ } else {
+ PTIME_CONSUME(4, {
+ for (int lpc = 0; lpc < 4; lpc++) {
+ if (str[off_inout + lpc] < '0' || str[off_inout + lpc] > '9') {
+ return false;
+ }
+ }
+ dst->et_flags |= ETF_MICROS_SET;
+ dst->et_nsec = ((str[off_inout + 0] - '0') * 100000
+ + (str[off_inout + 1] - '0') * 10000
+ + (str[off_inout + 2] - '0') * 1000
+ + (str[off_inout + 3] - '0') * 100)
+ * 1000;
+ });
+ }
return true;
}
@@ -979,6 +1149,7 @@ ptime_N(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
return false;
}
}
+ dst->et_flags |= ETF_NANOS_SET;
dst->et_nsec = ((str[off_inout + 0] - '0') * 100000000
+ (str[off_inout + 1] - '0') * 10000000
+ (str[off_inout + 2] - '0') * 1000000
@@ -1082,8 +1253,8 @@ ptime_at(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
}
dst->et_flags |= ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET | ETF_HOUR_SET
- | ETF_MINUTE_SET | ETF_SECOND_SET | ETF_MACHINE_ORIENTED
- | ETF_EPOCH_TIME;
+ | ETF_MINUTE_SET | ETF_SECOND_SET | ETF_NANOS_SET | ETF_MACHINE_ORIENTED
+ | ETF_EPOCH_TIME | ETF_ZONE_SET;
return true;
}
@@ -1116,4 +1287,6 @@ extern struct ptime_fmt PTIMEC_FORMATS[];
extern const char* PTIMEC_FORMAT_STR[];
+extern size_t PTIMEC_DEFAULT_FMT_INDEX;
+
#endif