Home | History | Annotate | Download | only in liblog
      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 
     25 const char log_time::default_format[] = "%m-%d %H:%M:%S.%3q";
     26 const timespec log_time::EPOCH = { 0, 0 };
     27 
     28 // Add %#q for fractional seconds to standard strptime function
     29 
     30 char *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 
    136 log_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 
    153 log_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