diff -r 5754f069b123 Include/timemodule.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Include/timemodule.h Thu Dec 18 08:14:09 2014 -0800 @@ -0,0 +1,56 @@ +#ifndef Py_TIMEMODULE_H +#define Py_TIMEMODULE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_CLOCK_GETTIME +typedef struct timespec _PyTime_timespec; +#else +typedef struct { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +} _PyTime_timespec; +#endif + + +#define PyTime_CAPSULE_NAME "time._C_API" + +typedef struct { + PyTypeObject *StructTimespecType; + PyObject *(*PyStructTimespecFromCStructTimespec)(_PyTime_timespec *); + int (*PyStructTimespecToCStructTimespec)(PyObject*, _PyTime_timespec *); +} PyTime_C_API; + + +#ifndef TIME_MODULE + +static PyTime_C_API *api = NULL; + +#define PyStructTimespecFromCStructTimespec \ + api->PyStructTimespecFromCStructTimespec + +#define PyStructTimespecToCStructTimespec \ + api->PyStructTimespecToCStructTimespec + +#define StructTimespec_Check(op) \ + PyObject_TypeCheck(op, api->StructTimespecType) + +#define StructTimespec_CheckExact(op) \ + (Py_TYPE(op) == api->StructTimespecType) + +static int +import_time(void) +{ + api = (PyTime_C_API*)PyCapsule_Import(PyTime_CAPSULE_NAME, 0); + return (api != NULL) ? 0 : -1; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(Py_TIMEMODULE_H) */ + diff -r 5754f069b123 Modules/timemodule.c --- a/Modules/timemodule.c Sat Nov 22 12:54:57 2014 -0800 +++ b/Modules/timemodule.c Thu Dec 18 08:14:09 2014 -0800 @@ -30,6 +30,9 @@ #endif /* MS_WINDOWS */ #endif /* !__WATCOMC__ || __QNX__ */ +#define TIME_MODULE +#include "timemodule.h" + /* Forward declarations */ static int floatsleep(double); static PyObject* floattime(_Py_clock_info_t *info); @@ -270,8 +273,25 @@ 9, }; +static PyStructSequence_Field struct_timespec_type_fields[] = { + {"tv_sec", "seconds"}, + {"tv_nsec", "nanoseconds"}, + {0} +}; + +static PyStructSequence_Desc struct_timespec_type_desc = { + "time.struct_timespec", + "POSIX.1b structure for a time value.", + struct_timespec_type_fields, + 2, +}; + + static int initialized; static PyTypeObject StructTimeType; +static PyTypeObject StructTimespecType; +#define StructTimespec_Check(op) PyObject_TypeCheck(op, &StructTimespecType) +#define StructTimespec_CheckExact(op) (Py_TYPE(op) == &StructTimespecType) static PyObject * @@ -1284,13 +1304,13 @@ PyDoc_STRVAR(module_doc, "This module provides various functions to manipulate time values.\n\ \n\ -There are two standard representations of time. One is the number\n\ +There are three standard representations of time. One is the number\n\ of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\ or a floating point number (to represent fractions of seconds).\n\ The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\ The actual value can be retrieved by calling gmtime(0).\n\ \n\ -The other representation is a tuple of 9 integers giving local time.\n\ +Another representation is a tuple of 9 integers giving local time.\n\ The tuple items are:\n\ year (including century, e.g. 1998)\n\ month (1-12)\n\ @@ -1305,6 +1325,11 @@ if it is 1, the time is given in the DST time zone;\n\ if it is -1, mktime() should guess based on the date and time.\n\ \n\ +The other representation is a tuple of 2 integers similar to POSIX.1b\n\ +struct timespec. The tuple items are:\n\ + seconds\n\ + nanoseconds (0-999999999)\n\ +\n\ Variables:\n\ \n\ timezone -- difference in seconds between UTC and local standard time\n\ @@ -1340,10 +1365,51 @@ NULL }; +/* + * C API capsule + */ + +static PyObject * +PyStructTimespecFromCStructTimespec(_PyTime_timespec * ts) +{ + PyObject *v = PyStructSequence_New(&StructTimespecType); + if (v == NULL) + return NULL; + +#define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val)) + SET(0, ts->tv_sec); + SET(1, ts->tv_nsec); +#undef SET + if (PyErr_Occurred()) { + Py_XDECREF(v); + return NULL; + } + + return v; +} + +int PyStructTimespecToCStructTimespec(PyObject* obj, _PyTime_timespec * ts) +{ + + if (! StructTimespec_Check(obj)) + return -1; + + ts->tv_sec = PyLong_AsLong(PyStructSequence_GET_ITEM(obj,0)); + ts->tv_nsec = PyLong_AsLong(PyStructSequence_GET_ITEM(obj,1)); + + return 0; +} + +static PyTime_C_API api = { + &StructTimespecType, + &PyStructTimespecFromCStructTimespec, + &PyStructTimespecToCStructTimespec +}; + PyMODINIT_FUNC PyInit_time(void) { - PyObject *m; + PyObject *m, *c; m = PyModule_Create(&timemodule); if (m == NULL) return NULL; @@ -1355,14 +1421,25 @@ if (PyStructSequence_InitType2(&StructTimeType, &struct_time_type_desc) < 0) return NULL; + if (PyStructSequence_InitType2(&StructTimespecType, + &struct_timespec_type_desc) < 0) + return NULL; } Py_INCREF(&StructTimeType); + Py_INCREF(&StructTimespecType); #ifdef HAVE_STRUCT_TM_TM_ZONE PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 11); #else PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 9); #endif PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType); + PyModule_AddObject(m, "struct_timespec", (PyObject*) &StructTimespecType); + + c = PyCapsule_New(&api, PyTime_CAPSULE_NAME, NULL); + if (c == NULL) + return NULL; + PyModule_AddObject(m, "_C_API", c); + initialized = 1; return m; }