util_mit.cc

Go to the documentation of this file.
00001 // -*- mode: c++; c-basic-offset:4 -*-
00002 
00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00004 // Access Protocol.
00005 
00006 // Copyright (c) 2002 OPeNDAP, Inc.
00007 // Author: James Gallagher <jgallagher@opendap.org>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112
00024 
00025 // This file was derived from the libwww source code of 1998/08/20. The
00026 // copyright for the source of this derivative work can be found in the file
00027 // COPYRIGHT_W3C.
00028 
00029 
00030 #include "config.h"
00031 
00032 static char rcsid[] not_used =
00033     {"$Id: util_mit.cc 16088 2007-03-28 21:42:19Z jimg $"
00034     };
00035 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string>
00039 #include <ctype.h>
00040 
00041 #ifndef TM_IN_SYS_TIME
00042 #include <time.h>
00043 #else
00044 #include <sys/time.h>
00045 #endif
00046 
00047 #include <sys/types.h>
00048 #include <sys/stat.h>
00049 
00050 #include <iostream>
00051 
00052 #include "util_mit.h"
00053 
00054 using std::cerr;
00055 using std::endl;
00056 using std::string;
00057 
00058 #include "debug.h"
00059 
00060 static char * months[12] =
00061     {
00062         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00063     };
00064 
00065 #ifndef HAVE_STRFTIME
00066 static char * wkdays[7] =
00067     {
00068         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00069     };
00070 #endif
00071 
00072 /* Upper- and Lowercase macros
00073 
00074    The problem here is that toupper(x) is not defined officially unless
00075    isupper(x) is. These macros are CERTAINLY needed on #if defined(pyr) ||
00076    define(mips) or BDSI platforms. For safefy, we make them mandatory.
00077 */
00078 
00079 #ifndef TOLOWER
00080 #define TOLOWER(c) tolower((int) (c))
00081 #define TOUPPER(c) toupper((int) (c))
00082 #endif
00083 
00084 static int
00085 strncasecomp(const char *a, const char *b, int n)
00086 {
00087     const char *p = a;
00088     const char *q = b;
00089 
00090     for (p = a, q = b;; p++, q++) {
00091         int diff;
00092         if (p == a + n) return 0; /*   Match up to n characters */
00093         if (!(*p && *q)) return *p - *q;
00094         diff = TOLOWER(*p) - TOLOWER(*q);
00095         if (diff) return diff;
00096     }
00097     /*NOTREACHED*/
00098 }
00099 
00100 static int
00101 make_month(char * s, char ** ends)
00102 {
00103     char * ptr = s;
00104     while (!isalpha((int) *ptr)) ptr++;
00105     if (*ptr) {
00106         int i;
00107         *ends = ptr + 3;
00108         for (i = 0; i < 12; i++)
00109             if (!strncasecomp(months[i], ptr, 3)) return i;
00110     }
00111     return 0;
00112 }
00113 
00128 time_t
00129 parse_time(const char * str, bool expand)
00130 {
00131     char * s;
00132     struct tm tm;
00133     time_t t;
00134 
00135     if (!str) return 0;
00136 
00137     if ((s = (char *)strchr(str, ','))) {  /* Thursday, 10-Jun-93 01:29:59 GMT */
00138         s++;    /* or: Thu, 10 Jan 1993 01:29:59 GMT */
00139         while (*s && *s == ' ') s++;
00140         if (strchr(s, '-')) {         /* First format */
00141             DBG(cerr << "Format...... Weekday, 00-Mon-00 00:00:00 GMT"
00142                 << endl);
00143             if ((int)strlen(s) < 18) {
00144                 DBG(cerr << "ERROR....... Not a valid time format \""
00145                     << s << "\"" << endl);
00146                 return 0;
00147             }
00148             tm.tm_mday = strtol(s, &s, 10);
00149             tm.tm_mon = make_month(s, &s);
00150             ++s;
00151             tm.tm_year = strtol(s, &s, 10);
00152             tm.tm_hour = strtol(s, &s, 10);
00153             ++s;
00154             tm.tm_min = strtol(s, &s, 10);
00155             ++s;
00156             tm.tm_sec = strtol(s, &s, 10);
00157 
00158         }
00159         else {         /* Second format */
00160             DBG(cerr << "Format...... Wkd, 00 Mon 0000 00:00:00 GMT" << endl);
00161             if ((int)strlen(s) < 20) {
00162                 DBG(cerr << "ERROR....... Not a valid time format \""
00163                     << s << "\"" << endl);
00164                 return 0;
00165             }
00166             tm.tm_mday = strtol(s, &s, 10);
00167             tm.tm_mon = make_month(s, &s);
00168             tm.tm_year = strtol(s, &s, 10) - 1900;
00169             tm.tm_hour = strtol(s, &s, 10);
00170             ++s;
00171             tm.tm_min = strtol(s, &s, 10);
00172             ++s;
00173             tm.tm_sec = strtol(s, &s, 10);
00174         }
00175     }
00176     else if (isdigit((int) *str)) {
00177 
00178         if (strchr(str, 'T')) { /* ISO (limited format) date string */
00179             DBG(cerr << "Format...... YYYY.MM.DDThh:mmStzWkd" << endl);
00180             s = (char *) str;
00181             while (*s && *s == ' ') s++;
00182             if ((int)strlen(s) < 21) {
00183                 DBG(cerr << "ERROR....... Not a valid time format \""
00184                     << s << "\"" << endl);
00185                 return 0;
00186             }
00187             tm.tm_year = strtol(s, &s, 10) - 1900;
00188             ++s;
00189             tm.tm_mon  = strtol(s, &s, 10);
00190             ++s;
00191             tm.tm_mday = strtol(s, &s, 10);
00192             ++s;
00193             tm.tm_hour = strtol(s, &s, 10);
00194             ++s;
00195             tm.tm_min  = strtol(s, &s, 10);
00196             ++s;
00197             tm.tm_sec  = strtol(s, &s, 10);
00198 
00199         }
00200         else {         /* delta seconds */
00201             t = expand ? time(NULL) + atol(str) : atol(str);
00202 
00203             return t;
00204         }
00205 
00206     }
00207     else {       /* Try the other format:  Wed Jun  9 01:29:59 1993 GMT */
00208         DBG(cerr << "Format...... Wkd Mon 00 00:00:00 0000 GMT" << endl);
00209         s = (char *) str;
00210         while (*s && *s == ' ') s++;
00211         DBG(cerr << "Trying...... The Wrong time format: " << s << endl);
00212         if ((int)strlen(s) < 24) {
00213             DBG(cerr << "ERROR....... Not a valid time format \""
00214                 << s << "\"" << endl);
00215             return 0;
00216         }
00217         tm.tm_mon = make_month(s, &s);
00218         tm.tm_mday = strtol(s, &s, 10);
00219         tm.tm_hour = strtol(s, &s, 10);
00220         ++s;
00221         tm.tm_min = strtol(s, &s, 10);
00222         ++s;
00223         tm.tm_sec = strtol(s, &s, 10);
00224         tm.tm_year = strtol(s, &s, 10) - 1900;
00225     }
00226     if (tm.tm_sec  < 0  ||  tm.tm_sec  > 59  ||
00227         tm.tm_min  < 0  ||  tm.tm_min  > 59  ||
00228         tm.tm_hour < 0  ||  tm.tm_hour > 23  ||
00229         tm.tm_mday < 1  ||  tm.tm_mday > 31  ||
00230         tm.tm_mon  < 0  ||  tm.tm_mon  > 11  ||
00231         tm.tm_year < 70  ||  tm.tm_year > 120) {
00232         DBG(cerr << "ERROR....... Parsed illegal time" << endl);
00233         return 0;
00234     }
00235 
00236     /* Let mktime decide whether we have DST or not */
00237     tm.tm_isdst = -1;
00238 
00239 #ifdef HAVE_TIMEGM
00240 
00241     t = timegm(&tm);
00242 
00243 #else
00244 
00245 #ifdef HAVE_MKTIME
00246 
00247     // Compute offset between localtime and GMT.
00248     time_t offset;
00249     time_t now = time(0);
00250 #ifdef _REENTRANT
00251     struct tm gmt, local;
00252     offset = mktime(gmtime_r(&now, &gmt)) - mktime(localtime_r(&now, &local));
00253 #else
00254     offset = mktime(gmtime(&now)) - mktime(localtime(&now));
00255 #endif
00256 
00257     t = mktime(&tm) + offset;
00258 
00259 #else
00260 
00261 #error "Neither mktime nor timegm defined"
00262 
00263 #endif /* HAVE_TIMEGM */
00264 #endif /* HAVE_MKTIME */
00265 
00266     DBG(cerr << "Time string. " << str << " parsed to " << t
00267         << " calendar time or \"" << ctime(&t) << "\" in local time" << endl);
00268 
00269     return t;
00270 }
00271 
00281 string date_time_str(time_t *calendar, bool local)
00282 {
00283     char buf[40];
00284 
00285 #ifdef HAVE_STRFTIME
00286     if (local) {
00287         /*
00288         ** Solaris 2.3 has a bug so we _must_ use reentrant version
00289         ** Thomas Maslen <tmaslen@verity.com>
00290         */
00291 #if defined(_REENTRANT) || defined(SOLARIS)
00292         struct tm loctime;
00293         localtime_r(calendar, &loctime);
00294         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime);
00295 #else
00296         struct tm *loctime = localtime(calendar);
00297         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
00298 #endif /* SOLARIS || _REENTRANT */
00299     }
00300     else {
00301 #if defined(_REENTRANT) || defined(SOLARIS)
00302         struct tm gmt;
00303         gmtime_r(calendar, &gmt);
00304         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt);
00305 #else
00306         struct tm *gmt = gmtime(calendar);
00307         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
00308 #endif /* SOLARIS || _REENTRANT */
00309     }
00310 
00311 #else  /* !HAVE_STRFTIME */
00312 
00313     if (local) {
00314 #if defined(_REENTRANT)
00315         struct tm loctime;
00316         localtime_r(calendar, &loctime);
00317         sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
00318                 wkdays[loctime.tm_wday],
00319                 loctime.tm_mday,
00320                 months[loctime.tm_mon],
00321                 loctime.tm_year + 1900,
00322                 loctime.tm_hour,
00323                 loctime.tm_min,
00324                 loctime.tm_sec);
00325 #else
00326     struct tm *loctime = localtime(calendar);
00327     sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
00328             wkdays[loctime->tm_wday],
00329             loctime->tm_mday,
00330             months[loctime->tm_mon],
00331             loctime->tm_year + 1900,
00332             loctime->tm_hour,
00333             loctime->tm_min,
00334             loctime->tm_sec);
00335 #endif /* _REENTRANT */
00336     }
00337     else {
00338 #if defined(_REENTRANT) || defined(SOLARIS)
00339         struct tm gmt;
00340         gmtime_r(calendar, &gmt);
00341         sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
00342                 wkdays[gmt.tm_wday],
00343                 gmt.tm_mday,
00344                 months[gmt.tm_mon],
00345                 gmt.tm_year + 1900,
00346                 gmt.tm_hour,
00347                 gmt.tm_min,
00348                 gmt.tm_sec);
00349 #else
00350     struct tm *gmt = gmtime(calendar);
00351     sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
00352             wkdays[gmt->tm_wday],
00353             gmt->tm_mday,
00354             months[gmt->tm_mon],
00355             gmt->tm_year + 1900,
00356             gmt->tm_hour,
00357             gmt->tm_min,
00358             gmt->tm_sec);
00359 #endif
00360     }
00361 #endif
00362     return string(buf);
00363 }

Generated on Wed Jun 27 12:56:39 2007 for libdap++ by  doxygen 1.4.7