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#include <sys/cdefs.h> 22 23#include <log/log_read.h> 24 25const char log_time::default_format[] = "%m-%d %H:%M:%S.%3q"; 26const timespec log_time::EPOCH = { 0, 0 }; 27 28// Add %#q for fractional seconds to standard strptime function 29 30char *log_time::strptime(const char *s, const char *format) { 31 time_t now; 32#ifdef __linux__ 33 *this = log_time(CLOCK_REALTIME); 34 now = tv_sec; 35#else 36 time(&now); 37 tv_sec = now; 38 tv_nsec = 0; 39#endif 40 41 struct tm *ptm; 42#if (defined(HAVE_LOCALTIME_R)) 43 struct tm tmBuf; 44 ptm = localtime_r(&now, &tmBuf); 45#else 46 ptm = localtime(&now); 47#endif 48 49 char fmt[strlen(format) + 1]; 50 strcpy(fmt, format); 51 52 char *ret = const_cast<char *> (s); 53 char *cp; 54 for (char *f = cp = fmt; ; ++cp) { 55 if (!*cp) { 56 if (f != cp) { 57 ret = ::strptime(ret, f, ptm); 58 } 59 break; 60 } 61 if (*cp != '%') { 62 continue; 63 } 64 char *e = cp; 65 ++e; 66#if (defined(__BIONIC__)) 67 if (*e == 's') { 68 *cp = '\0'; 69 if (*f) { 70 ret = ::strptime(ret, f, ptm); 71 if (!ret) { 72 break; 73 } 74 } 75 tv_sec = 0; 76 while (isdigit(*ret)) { 77 tv_sec = tv_sec * 10 + *ret - '0'; 78 ++ret; 79 } 80 now = tv_sec; 81#if (defined(HAVE_LOCALTIME_R)) 82 ptm = localtime_r(&now, &tmBuf); 83#else 84 ptm = localtime(&now); 85#endif 86 } else 87#endif 88 { 89 unsigned num = 0; 90 while (isdigit(*e)) { 91 num = num * 10 + *e - '0'; 92 ++e; 93 } 94 if (*e != 'q') { 95 continue; 96 } 97 *cp = '\0'; 98 if (*f) { 99 ret = ::strptime(ret, f, ptm); 100 if (!ret) { 101 break; 102 } 103 } 104 unsigned long mul = NS_PER_SEC; 105 if (num == 0) { 106 num = INT_MAX; 107 } 108 tv_nsec = 0; 109 while (isdigit(*ret) && num && (mul > 1)) { 110 --num; 111 mul /= 10; 112 tv_nsec = tv_nsec + (*ret - '0') * mul; 113 ++ret; 114 } 115 } 116 f = cp = e; 117 ++f; 118 } 119 120 if (ret) { 121 tv_sec = mktime(ptm); 122 return ret; 123 } 124 125 // Upon error, place a known value into the class, the current time. 126#ifdef __linux__ 127 *this = log_time(CLOCK_REALTIME); 128#else 129 time(&now); 130 tv_sec = now; 131 tv_nsec = 0; 132#endif 133 return ret; 134} 135 136log_time log_time::operator-= (const timespec &T) { 137 // No concept of negative time, clamp to EPOCH 138 if (*this <= T) { 139 return *this = EPOCH; 140 } 141 142 if (this->tv_nsec < (unsigned long int)T.tv_nsec) { 143 --this->tv_sec; 144 this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec; 145 } else { 146 this->tv_nsec -= T.tv_nsec; 147 } 148 this->tv_sec -= T.tv_sec; 149 150 return *this; 151} 152 153log_time log_time::operator-= (const log_time &T) { 154 // No concept of negative time, clamp to EPOCH 155 if (*this <= T) { 156 return *this = EPOCH; 157 } 158 159 if (this->tv_nsec < T.tv_nsec) { 160 --this->tv_sec; 161 this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec; 162 } else { 163 this->tv_nsec -= T.tv_nsec; 164 } 165 this->tv_sec -= T.tv_sec; 166 167 return *this; 168} 169