blob: 3fbe1cbc564ac58c466900cd159e73e556e5426c [file] [log] [blame]
Mark Salyzynfa3716b2014-02-14 16:05:05 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <ctype.h>
18#include <limits.h>
19#include <stdio.h>
20#include <string.h>
Mark Salyzynfa3716b2014-02-14 16:05:05 -080021
Mark Salyzynaeaaf812016-09-30 13:30:33 -070022#include <private/android_logger.h>
Mark Salyzynfa3716b2014-02-14 16:05:05 -080023
Tom Cherry2d9779e2019-02-08 11:46:19 -080024const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
25const timespec log_time::EPOCH = {0, 0};
Mark Salyzynfa3716b2014-02-14 16:05:05 -080026
27// Add %#q for fractional seconds to standard strptime function
28
Tom Cherry2d9779e2019-02-08 11:46:19 -080029char* log_time::strptime(const char* s, const char* format) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080030 time_t now;
Mark Salyzynfa3716b2014-02-14 16:05:05 -080031#ifdef __linux__
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080032 *this = log_time(CLOCK_REALTIME);
33 now = tv_sec;
Mark Salyzynfa3716b2014-02-14 16:05:05 -080034#else
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080035 time(&now);
36 tv_sec = now;
37 tv_nsec = 0;
Mark Salyzynfa3716b2014-02-14 16:05:05 -080038#endif
39
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080040 struct tm* ptm;
Yabin Cui8a985352014-11-13 10:02:08 -080041#if !defined(_WIN32)
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080042 struct tm tmBuf;
43 ptm = localtime_r(&now, &tmBuf);
Mark Salyzynfa3716b2014-02-14 16:05:05 -080044#else
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080045 ptm = localtime(&now);
Mark Salyzynfa3716b2014-02-14 16:05:05 -080046#endif
47
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080048 char fmt[strlen(format) + 1];
49 strcpy(fmt, format);
Mark Salyzynfa3716b2014-02-14 16:05:05 -080050
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080051 char* ret = const_cast<char*>(s);
52 char* cp;
53 for (char* f = cp = fmt;; ++cp) {
54 if (!*cp) {
55 if (f != cp) {
56 ret = ::strptime(ret, f, ptm);
57 }
58 break;
59 }
60 if (*cp != '%') {
61 continue;
62 }
63 char* e = cp;
64 ++e;
Mark Salyzynfa3716b2014-02-14 16:05:05 -080065#if (defined(__BIONIC__))
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080066 if (*e == 's') {
67 *cp = '\0';
68 if (*f) {
69 ret = ::strptime(ret, f, ptm);
70 if (!ret) {
71 break;
Mark Salyzynfa3716b2014-02-14 16:05:05 -080072 }
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080073 }
74 tv_sec = 0;
75 while (isdigit(*ret)) {
76 tv_sec = tv_sec * 10 + *ret - '0';
77 ++ret;
78 }
79 now = tv_sec;
80#if !defined(_WIN32)
81 ptm = localtime_r(&now, &tmBuf);
Mark Salyzynfa3716b2014-02-14 16:05:05 -080082#else
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080083 ptm = localtime(&now);
Mark Salyzynfa3716b2014-02-14 16:05:05 -080084#endif
Mark Salyzyn2ed51d72017-03-09 08:09:43 -080085 } else
86#endif
87 {
88 unsigned num = 0;
89 while (isdigit(*e)) {
90 num = num * 10 + *e - '0';
91 ++e;
92 }
93 if (*e != 'q') {
94 continue;
95 }
96 *cp = '\0';
97 if (*f) {
98 ret = ::strptime(ret, f, ptm);
99 if (!ret) {
100 break;
101 }
102 }
103 unsigned long mul = NS_PER_SEC;
104 if (num == 0) {
105 num = INT_MAX;
106 }
107 tv_nsec = 0;
108 while (isdigit(*ret) && num && (mul > 1)) {
109 --num;
110 mul /= 10;
111 tv_nsec = tv_nsec + (*ret - '0') * mul;
112 ++ret;
113 }
114 }
115 f = cp = e;
116 ++f;
117 }
118
119 if (ret) {
120 tv_sec = mktime(ptm);
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800121 return ret;
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800122 }
123
124// Upon error, place a known value into the class, the current time.
125#ifdef __linux__
126 *this = log_time(CLOCK_REALTIME);
127#else
128 time(&now);
129 tv_sec = now;
130 tv_nsec = 0;
131#endif
132 return ret;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800133}
134
Tom Cherry2d9779e2019-02-08 11:46:19 -0800135log_time log_time::operator-=(const timespec& T) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800136 // No concept of negative time, clamp to EPOCH
137 if (*this <= T) {
Bernie Innocenti804e7d82019-01-16 15:25:18 +0900138 return *this = log_time(EPOCH);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800139 }
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800140
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800141 if (this->tv_nsec < (unsigned long int)T.tv_nsec) {
142 --this->tv_sec;
143 this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
144 } else {
145 this->tv_nsec -= T.tv_nsec;
146 }
147 this->tv_sec -= T.tv_sec;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800148
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800149 return *this;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800150}
151
Tom Cherry2d9779e2019-02-08 11:46:19 -0800152log_time log_time::operator+=(const timespec& T) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800153 this->tv_nsec += (unsigned long int)T.tv_nsec;
154 if (this->tv_nsec >= NS_PER_SEC) {
155 this->tv_nsec -= NS_PER_SEC;
156 ++this->tv_sec;
157 }
158 this->tv_sec += T.tv_sec;
Mark Salyzyndecd9292014-10-13 14:13:18 -0700159
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800160 return *this;
Mark Salyzyndecd9292014-10-13 14:13:18 -0700161}
162
Tom Cherry2d9779e2019-02-08 11:46:19 -0800163log_time log_time::operator-=(const log_time& T) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800164 // No concept of negative time, clamp to EPOCH
165 if (*this <= T) {
Bernie Innocenti804e7d82019-01-16 15:25:18 +0900166 return *this = log_time(EPOCH);
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800167 }
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800168
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800169 if (this->tv_nsec < T.tv_nsec) {
170 --this->tv_sec;
171 this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
172 } else {
173 this->tv_nsec -= T.tv_nsec;
174 }
175 this->tv_sec -= T.tv_sec;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800176
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800177 return *this;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800178}
Mark Salyzyndecd9292014-10-13 14:13:18 -0700179
Tom Cherry2d9779e2019-02-08 11:46:19 -0800180log_time log_time::operator+=(const log_time& T) {
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800181 this->tv_nsec += T.tv_nsec;
182 if (this->tv_nsec >= NS_PER_SEC) {
183 this->tv_nsec -= NS_PER_SEC;
184 ++this->tv_sec;
185 }
186 this->tv_sec += T.tv_sec;
Mark Salyzyndecd9292014-10-13 14:13:18 -0700187
Mark Salyzyn2ed51d72017-03-09 08:09:43 -0800188 return *this;
Mark Salyzyndecd9292014-10-13 14:13:18 -0700189}