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 18315 2008-03-03 20:14:44Z jimg $"
00034     };
00035 
00036 #include <cstring>
00037 #include <cstdlib>
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 namespace libdap {
00061 
00062 static char * months[12] =
00063     {
00064         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00065     };
00066 
00067 #ifndef HAVE_STRFTIME
00068 static char * wkdays[7] =
00069     {
00070         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00071     };
00072 #endif
00073 
00074 /* Upper- and Lowercase macros
00075 
00076    The problem here is that toupper(x) is not defined officially unless
00077    isupper(x) is. These macros are CERTAINLY needed on #if defined(pyr) ||
00078    define(mips) or BDSI platforms. For safefy, we make them mandatory.
00079 */
00080 
00081 #ifndef TOLOWER
00082 #define TOLOWER(c) tolower((int) (c))
00083 #define TOUPPER(c) toupper((int) (c))
00084 #endif
00085 
00086 static int
00087 strncasecomp(const char *a, const char *b, int n)
00088 {
00089     const char *p = a;
00090     const char *q = b;
00091 
00092     for (p = a, q = b;; p++, q++) {
00093         int diff;
00094         if (p == a + n) return 0; /*   Match up to n characters */
00095         if (!(*p && *q)) return *p - *q;
00096         diff = TOLOWER(*p) - TOLOWER(*q);
00097         if (diff) return diff;
00098     }
00099     /*NOTREACHED*/
00100 }
00101 
00102 static int
00103 make_month(char * s, char ** ends)
00104 {
00105     char * ptr = s;
00106     while (!isalpha((int) *ptr)) ptr++;
00107     if (*ptr) {
00108         int i;
00109         *ends = ptr + 3;
00110         for (i = 0; i < 12; i++)
00111             if (!strncasecomp(months[i], ptr, 3)) return i;
00112     }
00113     return 0;
00114 }
00115 
00130 time_t
00131 parse_time(const char * str, bool expand)
00132 {
00133     char * s;
00134     struct tm tm;
00135     time_t t;
00136 
00137     if (!str) return 0;
00138 
00139     if ((s = (char *)strchr(str, ','))) {  /* Thursday, 10-Jun-93 01:29:59 GMT */
00140         s++;    /* or: Thu, 10 Jan 1993 01:29:59 GMT */
00141         while (*s && *s == ' ') s++;
00142         if (strchr(s, '-')) {         /* First format */
00143             DBG(cerr << "Format...... Weekday, 00-Mon-00 00:00:00 GMT"
00144                 << endl);
00145             if ((int)strlen(s) < 18) {
00146                 DBG(cerr << "ERROR....... Not a valid time format \""
00147                     << s << "\"" << endl);
00148                 return 0;
00149             }
00150             tm.tm_mday = strtol(s, &s, 10);
00151             tm.tm_mon = make_month(s, &s);
00152             ++s;
00153             tm.tm_year = strtol(s, &s, 10);
00154             tm.tm_hour = strtol(s, &s, 10);
00155             ++s;
00156             tm.tm_min = strtol(s, &s, 10);
00157             ++s;
00158             tm.tm_sec = strtol(s, &s, 10);
00159 
00160         }
00161         else {         /* Second format */
00162             DBG(cerr << "Format...... Wkd, 00 Mon 0000 00:00:00 GMT" << endl);
00163             if ((int)strlen(s) < 20) {
00164                 DBG(cerr << "ERROR....... Not a valid time format \""
00165                     << s << "\"" << endl);
00166                 return 0;
00167             }
00168             tm.tm_mday = strtol(s, &s, 10);
00169             tm.tm_mon = make_month(s, &s);
00170             tm.tm_year = strtol(s, &s, 10) - 1900;
00171             tm.tm_hour = strtol(s, &s, 10);
00172             ++s;
00173             tm.tm_min = strtol(s, &s, 10);
00174             ++s;
00175             tm.tm_sec = strtol(s, &s, 10);
00176         }
00177     }
00178     else if (isdigit((int) *str)) {
00179 
00180         if (strchr(str, 'T')) { /* ISO (limited format) date string */
00181             DBG(cerr << "Format...... YYYY.MM.DDThh:mmStzWkd" << endl);
00182             s = (char *) str;
00183             while (*s && *s == ' ') s++;
00184             if ((int)strlen(s) < 21) {
00185                 DBG(cerr << "ERROR....... Not a valid time format \""
00186                     << s << "\"" << endl);
00187                 return 0;
00188             }
00189             tm.tm_year = strtol(s, &s, 10) - 1900;
00190             ++s;
00191             tm.tm_mon  = strtol(s, &s, 10);
00192             ++s;
00193             tm.tm_mday = strtol(s, &s, 10);
00194             ++s;
00195             tm.tm_hour = strtol(s, &s, 10);
00196             ++s;
00197             tm.tm_min  = strtol(s, &s, 10);
00198             ++s;
00199             tm.tm_sec  = strtol(s, &s, 10);
00200 
00201         }
00202         else {         /* delta seconds */
00203             t = expand ? time(NULL) + atol(str) : atol(str);
00204 
00205             return t;
00206         }
00207 
00208     }
00209     else {       /* Try the other format:  Wed Jun  9 01:29:59 1993 GMT */
00210         DBG(cerr << "Format...... Wkd Mon 00 00:00:00 0000 GMT" << endl);
00211         s = (char *) str;
00212         while (*s && *s == ' ') s++;
00213         DBG(cerr << "Trying...... The Wrong time format: " << s << endl);
00214         if ((int)strlen(s) < 24) {
00215             DBG(cerr << "ERROR....... Not a valid time format \""
00216                 << s << "\"" << endl);
00217             return 0;
00218         }
00219         tm.tm_mon = make_month(s, &s);
00220         tm.tm_mday = strtol(s, &s, 10);
00221         tm.tm_hour = strtol(s, &s, 10);
00222         ++s;
00223         tm.tm_min = strtol(s, &s, 10);
00224         ++s;
00225         tm.tm_sec = strtol(s, &s, 10);
00226         tm.tm_year = strtol(s, &s, 10) - 1900;
00227     }
00228     if (tm.tm_sec  < 0  ||  tm.tm_sec  > 59  ||
00229         tm.tm_min  < 0  ||  tm.tm_min  > 59  ||
00230         tm.tm_hour < 0  ||  tm.tm_hour > 23  ||
00231         tm.tm_mday < 1  ||  tm.tm_mday > 31  ||
00232         tm.tm_mon  < 0  ||  tm.tm_mon  > 11  ||
00233         tm.tm_year < 70  ||  tm.tm_year > 120) {
00234         DBG(cerr << "ERROR....... Parsed illegal time" << endl);
00235         return 0;
00236     }
00237 
00238     /* Let mktime decide whether we have DST or not */
00239     tm.tm_isdst = -1;
00240 
00241 #ifdef HAVE_TIMEGM
00242 
00243     t = timegm(&tm);
00244 
00245 #else
00246 
00247 #ifdef HAVE_MKTIME
00248 
00249     // Compute offset between localtime and GMT.
00250     time_t offset;
00251     time_t now = time(0);
00252 #ifdef _REENTRANT
00253     struct tm gmt, local;
00254     offset = mktime(gmtime_r(&now, &gmt)) - mktime(localtime_r(&now, &local));
00255 #else
00256     offset = mktime(gmtime(&now)) - mktime(localtime(&now));
00257 #endif
00258 
00259     t = mktime(&tm) + offset;
00260 
00261 #else
00262 
00263 #error "Neither mktime nor timegm defined"
00264 
00265 #endif /* HAVE_TIMEGM */
00266 #endif /* HAVE_MKTIME */
00267 
00268     DBG(cerr << "Time string. " << str << " parsed to " << t
00269         << " calendar time or \"" << ctime(&t) << "\" in local time" << endl);
00270 
00271     return t;
00272 }
00273 
00283 string date_time_str(time_t *calendar, bool local)
00284 {
00285     char buf[40];
00286 
00287 #ifdef HAVE_STRFTIME
00288     if (local) {
00289         /*
00290         ** Solaris 2.3 has a bug so we _must_ use reentrant version
00291         ** Thomas Maslen <tmaslen@verity.com>
00292         */
00293 #if defined(_REENTRANT) || defined(SOLARIS)
00294         struct tm loctime;
00295         localtime_r(calendar, &loctime);
00296         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime);
00297 #else
00298         struct tm *loctime = localtime(calendar);
00299         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
00300 #endif /* SOLARIS || _REENTRANT */
00301     }
00302     else {
00303 #if defined(_REENTRANT) || defined(SOLARIS)
00304         struct tm gmt;
00305         gmtime_r(calendar, &gmt);
00306         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt);
00307 #else
00308         struct tm *gmt = gmtime(calendar);
00309         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
00310 #endif /* SOLARIS || _REENTRANT */
00311     }
00312 
00313 #else  /* !HAVE_STRFTIME */
00314 
00315     if (local) {
00316 #if defined(_REENTRANT)
00317         struct tm loctime;
00318         localtime_r(calendar, &loctime);
00319         sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
00320                 wkdays[loctime.tm_wday],
00321                 loctime.tm_mday,
00322                 months[loctime.tm_mon],
00323                 loctime.tm_year + 1900,
00324                 loctime.tm_hour,
00325                 loctime.tm_min,
00326                 loctime.tm_sec);
00327 #else
00328     struct tm *loctime = localtime(calendar);
00329     sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
00330             wkdays[loctime->tm_wday],
00331             loctime->tm_mday,
00332             months[loctime->tm_mon],
00333             loctime->tm_year + 1900,
00334             loctime->tm_hour,
00335             loctime->tm_min,
00336             loctime->tm_sec);
00337 #endif /* _REENTRANT */
00338     }
00339     else {
00340 #if defined(_REENTRANT) || defined(SOLARIS)
00341         struct tm gmt;
00342         gmtime_r(calendar, &gmt);
00343         sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
00344                 wkdays[gmt.tm_wday],
00345                 gmt.tm_mday,
00346                 months[gmt.tm_mon],
00347                 gmt.tm_year + 1900,
00348                 gmt.tm_hour,
00349                 gmt.tm_min,
00350                 gmt.tm_sec);
00351 #else
00352     struct tm *gmt = gmtime(calendar);
00353     sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
00354             wkdays[gmt->tm_wday],
00355             gmt->tm_mday,
00356             months[gmt->tm_mon],
00357             gmt->tm_year + 1900,
00358             gmt->tm_hour,
00359             gmt->tm_min,
00360             gmt->tm_sec);
00361 #endif
00362     }
00363 #endif
00364     return string(buf);
00365 }
00366 
00367 } // namespace libdap

Generated on Wed Apr 15 19:20:23 2009 for libdap++ by  doxygen 1.4.7