1fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn/*
2fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * Copyright (C) 2014 The Android Open Source Project
3fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn *
4fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
5fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * you may not use this file except in compliance with the License.
6fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * You may obtain a copy of the License at
7fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn *
8fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
9fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn *
10fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
11fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
12fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * See the License for the specific language governing permissions and
14fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn * limitations under the License.
15fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn */
16fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
17fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#include <ctype.h>
18fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#include <limits.h>
19fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#include <stdio.h>
20fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#include <string.h>
21fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
22aeaaf81c2cc8366ac4f66eb3d2fc85f9b8194982Mark Salyzyn#include <private/android_logger.h>
23fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
24facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include "log_portability.h"
256d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn
266d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PRIVATE const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
276d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PRIVATE const timespec log_time::EPOCH = { 0, 0 };
28fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
29fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn// Add %#q for fractional seconds to standard strptime function
30fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
312ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE char* log_time::strptime(const char* s, const char* format) {
322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  time_t now;
33fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#ifdef __linux__
342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  *this = log_time(CLOCK_REALTIME);
352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  now = tv_sec;
36fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#else
372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  time(&now);
382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  tv_sec = now;
392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  tv_nsec = 0;
40fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#endif
41fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct tm* ptm;
438a98535bcb48dfd4bfe3dfddddc82925a2f1502bYabin Cui#if !defined(_WIN32)
442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct tm tmBuf;
452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ptm = localtime_r(&now, &tmBuf);
46fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#else
472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ptm = localtime(&now);
48fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#endif
49fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char fmt[strlen(format) + 1];
512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  strcpy(fmt, format);
522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char* ret = const_cast<char*>(s);
542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char* cp;
552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  for (char* f = cp = fmt;; ++cp) {
562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (!*cp) {
572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (f != cp) {
582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        ret = ::strptime(ret, f, ptm);
592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (*cp != '%') {
632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      continue;
642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    char* e = cp;
662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ++e;
67fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#if (defined(__BIONIC__))
682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (*e == 's') {
692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      *cp = '\0';
702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (*f) {
712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        ret = ::strptime(ret, f, ptm);
722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (!ret) {
732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          break;
742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        }
752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      tv_sec = 0;
772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      while (isdigit(*ret)) {
782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        tv_sec = tv_sec * 10 + *ret - '0';
792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        ++ret;
802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      now = tv_sec;
828a98535bcb48dfd4bfe3dfddddc82925a2f1502bYabin Cui#if !defined(_WIN32)
832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      ptm = localtime_r(&now, &tmBuf);
84fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#else
852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      ptm = localtime(&now);
86fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#endif
872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    } else
88fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#endif
892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    {
902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      unsigned num = 0;
912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      while (isdigit(*e)) {
922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        num = num * 10 + *e - '0';
932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        ++e;
942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (*e != 'q') {
962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        continue;
972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      *cp = '\0';
992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (*f) {
1002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        ret = ::strptime(ret, f, ptm);
1012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (!ret) {
1022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          break;
103fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn        }
1042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
1052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      unsigned long mul = NS_PER_SEC;
1062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (num == 0) {
1072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        num = INT_MAX;
1082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
1092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      tv_nsec = 0;
1102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      while (isdigit(*ret) && num && (mul > 1)) {
1112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        --num;
1122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        mul /= 10;
1132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        tv_nsec = tv_nsec + (*ret - '0') * mul;
1142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        ++ret;
1152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
116fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn    }
1172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    f = cp = e;
1182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ++f;
1192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
120fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
1212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (ret) {
1222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    tv_sec = mktime(ptm);
1232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return ret;
1242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
125fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
1262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn// Upon error, place a known value into the class, the current time.
127fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#ifdef __linux__
1282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  *this = log_time(CLOCK_REALTIME);
129fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#else
1302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  time(&now);
1312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  tv_sec = now;
1322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  tv_nsec = 0;
133fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn#endif
1342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return ret;
135fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn}
136fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
1372ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE log_time log_time::operator-=(const timespec& T) {
1382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  // No concept of negative time, clamp to EPOCH
1392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (*this <= T) {
1402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return *this = EPOCH;
1412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (this->tv_nsec < (unsigned long int)T.tv_nsec) {
1442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    --this->tv_sec;
1452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
1462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else {
1472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    this->tv_nsec -= T.tv_nsec;
1482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  this->tv_sec -= T.tv_sec;
1502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return *this;
152fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn}
153fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn
1542ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE log_time log_time::operator+=(const timespec& T) {
1552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  this->tv_nsec += (unsigned long int)T.tv_nsec;
1562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (this->tv_nsec >= NS_PER_SEC) {
1572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    this->tv_nsec -= NS_PER_SEC;
1582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ++this->tv_sec;
1592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  this->tv_sec += T.tv_sec;
161decd92945fa8692b384a99da786bd43f6bc1ef3eMark Salyzyn
1622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return *this;
163decd92945fa8692b384a99da786bd43f6bc1ef3eMark Salyzyn}
164decd92945fa8692b384a99da786bd43f6bc1ef3eMark Salyzyn
1652ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE log_time log_time::operator-=(const log_time& T) {
1662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  // No concept of negative time, clamp to EPOCH
1672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (*this <= T) {
1682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return *this = EPOCH;
1692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (this->tv_nsec < T.tv_nsec) {
1722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    --this->tv_sec;
1732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
1742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else {
1752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    this->tv_nsec -= T.tv_nsec;
1762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  this->tv_sec -= T.tv_sec;
1782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return *this;
180fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn}
181decd92945fa8692b384a99da786bd43f6bc1ef3eMark Salyzyn
1822ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE log_time log_time::operator+=(const log_time& T) {
1832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  this->tv_nsec += T.tv_nsec;
1842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (this->tv_nsec >= NS_PER_SEC) {
1852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    this->tv_nsec -= NS_PER_SEC;
1862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ++this->tv_sec;
1872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  this->tv_sec += T.tv_sec;
189decd92945fa8692b384a99da786bd43f6bc1ef3eMark Salyzyn
1902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return *this;
191decd92945fa8692b384a99da786bd43f6bc1ef3eMark Salyzyn}
192