xref: /aosp_15_r20/system/logging/liblog/log_time.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
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 #define _POSIX_THREAD_SAFE_FUNCTIONS  // For mingw localtime_r().
18 
19 #include <ctype.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include <private/android_logger.h>
25 
26 // Add %#q for fractional seconds to standard strptime function
strptime(const char * s,const char * format)27 char* log_time::strptime(const char* s, const char* format) {
28   time_t now;
29 #ifdef __linux__
30   *this = log_time(CLOCK_REALTIME);
31   now = tv_sec;
32 #else
33   time(&now);
34   tv_sec = now;
35   tv_nsec = 0;
36 #endif
37 
38   struct tm tmBuf;
39   struct tm* ptm = localtime_r(&now, &tmBuf);
40 
41   char fmt[strlen(format) + 1];
42   strcpy(fmt, format);
43 
44   char* ret = const_cast<char*>(s);
45   char* cp;
46   for (char* f = cp = fmt;; ++cp) {
47     if (!*cp) {
48       if (f != cp) {
49         ret = ::strptime(ret, f, ptm);
50       }
51       break;
52     }
53     if (*cp != '%') {
54       continue;
55     }
56     char* e = cp;
57     ++e;
58 #if (defined(__BIONIC__))
59     if (*e == 's') {
60       *cp = '\0';
61       if (*f) {
62         ret = ::strptime(ret, f, ptm);
63         if (!ret) {
64           break;
65         }
66       }
67       tv_sec = 0;
68       while (isdigit(*ret)) {
69         tv_sec = tv_sec * 10 + *ret - '0';
70         ++ret;
71       }
72       now = tv_sec;
73       ptm = localtime_r(&now, &tmBuf);
74     } else
75 #endif
76     {
77       unsigned num = 0;
78       while (isdigit(*e)) {
79         num = num * 10 + *e - '0';
80         ++e;
81       }
82       if (*e != 'q') {
83         continue;
84       }
85       *cp = '\0';
86       if (*f) {
87         ret = ::strptime(ret, f, ptm);
88         if (!ret) {
89           break;
90         }
91       }
92       unsigned long mul = NS_PER_SEC;
93       if (num == 0) {
94         num = INT_MAX;
95       }
96       tv_nsec = 0;
97       while (isdigit(*ret) && num && (mul > 1)) {
98         --num;
99         mul /= 10;
100         tv_nsec = tv_nsec + (*ret - '0') * mul;
101         ++ret;
102       }
103     }
104     f = cp = e;
105     ++f;
106   }
107 
108   if (ret) {
109     tv_sec = mktime(ptm);
110     return ret;
111   }
112 
113 // Upon error, place a known value into the class, the current time.
114 #ifdef __linux__
115   *this = log_time(CLOCK_REALTIME);
116 #else
117   time(&now);
118   tv_sec = now;
119   tv_nsec = 0;
120 #endif
121   return ret;
122 }
123