minor: refactor C time helpers out to a new file

This commit is contained in:
Mike Dirolf 2009-12-01 11:37:12 -05:00
parent d9599059f1
commit 4e2dde1746
4 changed files with 209 additions and 171 deletions

View File

@ -30,6 +30,8 @@
#include <Python.h>
#include <datetime.h>
#include "time_helpers.h"
static PyObject* InvalidName;
static PyObject* InvalidDocument;
static PyObject* InvalidStringData;
@ -52,172 +54,7 @@ typedef int Py_ssize_t;
/* Maximum number of regex flags */
#define FLAGS_SIZE 7
/* TODO we ought to check that the malloc or asprintf was successful
* and raise an exception if not. */
#if defined(WIN32) || defined(_MSC_VER)
/* no mkgmtime on MSVC before VS 2005. this is terribly gross */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define GMTIME_INVERSE(time_struct) _mkgmtime64(time_struct)
#else
/* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
*/
/*
* Copyright (c) 1987, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Arthur David Olson of the National Cancer Institute.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
** Adapted from code provided by Robert Elz, who writes:
** The "best" way to do mktime I think is based on an idea of Bob
** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
** It does a binary search of the time_t space. Since time_t's are
** just 32 bits, its a max of 32 iterations (even at 64 bits it
** would still be very reasonable).
*/
#ifndef WRONG
#define WRONG (-1)
#endif /* !defined WRONG */
static int tmcomp(atmp, btmp)
register const struct tm * const atmp;
register const struct tm * const btmp;
{
register int result;
if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
result = atmp->tm_sec - btmp->tm_sec;
return result;
}
time_t mkgmtime(tmp)
struct tm * const tmp;
{
register int dir;
register int bits;
register int saved_seconds;
time_t t;
struct tm yourtm, *mytm;
yourtm = *tmp;
saved_seconds = yourtm.tm_sec;
yourtm.tm_sec = 0;
/*
** Calculate the number of magnitude bits in a time_t
** (this works regardless of whether time_t is
** signed or unsigned, though lint complains if unsigned).
*/
for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
;
/*
** If time_t is signed, then 0 is the median value,
** if time_t is unsigned, then 1 << bits is median.
*/
t = (t < 0) ? 0 : ((time_t) 1 << bits);
/* Some gmtime() implementations are broken and will return
* NULL for time_ts larger than 40 bits even on 64-bit platforms
* so we'll just cap it at 40 bits */
if(bits > 40) bits = 40;
for ( ; ; ) {
mytm = gmtime(&t);
if(!mytm) return WRONG;
dir = tmcomp(mytm, &yourtm);
if (dir != 0) {
if (bits-- < 0)
return WRONG;
if (bits < 0)
--t;
else if (dir > 0)
t -= (time_t) 1 << bits;
else t += (time_t) 1 << bits;
continue;
}
break;
}
t += saved_seconds;
return t;
}
#define GMTIME_INVERSE(time_struct) mkgmtime((time_struct))
#endif
/* This macro is basically an implementation of asprintf for win32
* We get the length of the int as string and malloc a buffer for it,
* returning -1 if that malloc fails. We then actually print to the
@ -234,14 +71,9 @@ struct tm * const tmp;
"%d", \
(i)))
#define STRCAT(dest, n, src) strcat_s((dest), (n), (src))
#define GMTIME(timeinfo, seconds) gmtime_s((timeinfo), (seconds))
#define LOCALTIME(timeinfo, seconds) localtime_s((timeinfo), (seconds))
#else
#define GMTIME_INVERSE(time_struct) timegm((time_struct))
#define INT2STRING(buffer, i) asprintf((buffer), "%d", (i))
#define STRCAT(dest, n, src) strcat((dest), (src))
#define GMTIME(timeinfo, seconds) gmtime_r((seconds), (timeinfo)), 0
#define LOCALTIME(timeinfo, seconds) localtime_r((seconds), (timeinfo)), 0
#endif
/* A buffer representing some data being encoded to BSON. */

163
pymongo/time_helpers.c Normal file
View File

@ -0,0 +1,163 @@
/* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
*/
/*
* Copyright (c) 1987, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Arthur David Olson of the National Cancer Institute.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
** Adapted from code provided by Robert Elz, who writes:
** The "best" way to do mktime I think is based on an idea of Bob
** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
** It does a binary search of the time_t space. Since time_t's are
** just 32 bits, its a max of 32 iterations (even at 64 bits it
** would still be very reasonable).
*/
/* This hack is just for MSVC before VS 2005. */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#include <time.h>
#ifndef WRONG
#define WRONG (-1)
#endif /* !defined WRONG */
static int tmcomp(atmp, btmp)
register const struct tm * const atmp;
register const struct tm * const btmp;
{
register int result;
if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
result = atmp->tm_sec - btmp->tm_sec;
return result;
}
time_t mkgmtime(tmp)
struct tm * const tmp;
{
register int dir;
register int bits;
register int saved_seconds;
time_t t;
struct tm yourtm, *mytm;
yourtm = *tmp;
saved_seconds = yourtm.tm_sec;
yourtm.tm_sec = 0;
/*
** Calculate the number of magnitude bits in a time_t
** (this works regardless of whether time_t is
** signed or unsigned, though lint complains if unsigned).
*/
for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
;
/*
** If time_t is signed, then 0 is the median value,
** if time_t is unsigned, then 1 << bits is median.
*/
t = (t < 0) ? 0 : ((time_t) 1 << bits);
/* Some gmtime() implementations are broken and will return
* NULL for time_ts larger than 40 bits even on 64-bit platforms
* so we'll just cap it at 40 bits */
if(bits > 40) bits = 40;
for ( ; ; ) {
mytm = gmtime(&t);
if(!mytm) return WRONG;
dir = tmcomp(mytm, &yourtm);
if (dir != 0) {
if (bits-- < 0)
return WRONG;
if (bits < 0)
--t;
else if (dir > 0)
t -= (time_t) 1 << bits;
else t += (time_t) 1 << bits;
continue;
}
break;
}
t += saved_seconds;
return t;
}
#endif

40
pymongo/time_helpers.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright 2009 10gen, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TIME_HELPERS_H
#define TIME_HELPERS_H
#include <time.h>
/*
* Some helpers for dealing with time stuff in a cross platform way.
*/
#if defined(WIN32) || defined(_MSC_VER)
/* No mkgmtime on MSVC before VS 2005.
* This is terribly gross (see time_helpers.c). */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define GMTIME_INVERSE(time_struct) _mkgmtime64(time_struct)
#else
#define GMTIME_INVERSE(time_struct) mkgmtime((time_struct))
#define GMTIME(timeinfo, seconds) gmtime_s((timeinfo), (seconds))
#define LOCALTIME(timeinfo, seconds) localtime_s((timeinfo), (seconds))
#endif
#define GMTIME_INVERSE(time_struct) timegm((time_struct))
#define GMTIME(timeinfo, seconds) gmtime_r((seconds), (timeinfo)), 0
#define LOCALTIME(timeinfo, seconds) localtime_r((seconds), (timeinfo)), 0
#endif
#endif

View File

@ -117,7 +117,10 @@ although they do result in significant speed improvements.
c_ext = Feature(
"optional C extension",
standard=True,
ext_modules=[Extension('pymongo._cbson', ['pymongo/_cbsonmodule.c'])])
ext_modules=[Extension('pymongo._cbson',
include_dirs=['pymongo'],
sources=['pymongo/_cbsonmodule.c',
'pymongo/time_helpers.c'])])
if "--no_ext" in sys.argv:
sys.argv = [x for x in sys.argv if x != "--no_ext"]