• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
21 
22 #include <private/android_logger.h>
23 
24 const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
25 const timespec log_time::EPOCH = {0, 0};
26 
27 // Add %#q for fractional seconds to standard strptime function
28 
strptime(const char * s,const char * format)29 char* log_time::strptime(const char* s, const char* format) {
30   time_t now;
31 #ifdef __linux__
32   *this = log_time(CLOCK_REALTIME);
33   now = tv_sec;
34 #else
35   time(&now);
36   tv_sec = now;
37   tv_nsec = 0;
38 #endif
39 
40   struct tm* ptm;
41 #if !defined(_WIN32)
42   struct tm tmBuf;
43   ptm = localtime_r(&now, &tmBuf);
44 #else
45   ptm = localtime(&now);
46 #endif
47 
48   char fmt[strlen(format) + 1];
49   strcpy(fmt, format);
50 
51   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;
65 #if (defined(__BIONIC__))
66     if (*e == 's') {
67       *cp = '\0';
68       if (*f) {
69         ret = ::strptime(ret, f, ptm);
70         if (!ret) {
71           break;
72         }
73       }
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);
82 #else
83       ptm = localtime(&now);
84 #endif
85     } 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);
121     return ret;
122   }
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;
133 }
134 
operator -=(const timespec & T)135 log_time log_time::operator-=(const timespec& T) {
136   // No concept of negative time, clamp to EPOCH
137   if (*this <= T) {
138     return *this = log_time(EPOCH);
139   }
140 
141   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;
148 
149   return *this;
150 }
151 
operator +=(const timespec & T)152 log_time log_time::operator+=(const timespec& T) {
153   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;
159 
160   return *this;
161 }
162 
operator -=(const log_time & T)163 log_time log_time::operator-=(const log_time& T) {
164   // No concept of negative time, clamp to EPOCH
165   if (*this <= T) {
166     return *this = log_time(EPOCH);
167   }
168 
169   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;
176 
177   return *this;
178 }
179 
operator +=(const log_time & T)180 log_time log_time::operator+=(const log_time& T) {
181   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;
187 
188   return *this;
189 }
190