Minor fiddling to make the next part easier. Introduced an internal
authorTim Peters <tim.peters@gmail.com>
Sat, 11 Jan 2003 00:15:54 +0000 (00:15 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 11 Jan 2003 00:15:54 +0000 (00:15 +0000)
HASTZINFO() macro.

Include/datetime.h
Modules/datetimemodule.c

index 5c311620b929c33b700ac6bd0bea615078351658..4df0753f3021467d3b2485766916aabc434de94a 100644 (file)
 /* # of bytes for year, month, day, hour, minute, second, and usecond. */
 #define _PyDateTime_DATETIME_DATASIZE 10
 
-#define _PyTZINFO_HEAD         \
-       PyObject_HEAD           \
-       long hashcode;          \
-       char hastzinfo;         /* boolean flag */
 
 typedef struct
 {
        PyObject_HEAD
-       long hashcode;
-       unsigned char data[_PyDateTime_DATE_DATASIZE];
-} PyDateTime_Date;
+       long hashcode;          /* -1 when unknown */
+       int days;               /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
+       int seconds;            /* 0 <= seconds < 24*3600 is invariant */
+       int microseconds;       /* 0 <= microseconds < 1000000 is invariant */
+} PyDateTime_Delta;
 
 typedef struct
 {
-       PyObject_HEAD
-       long hashcode;
-       unsigned char data[_PyDateTime_DATETIME_DATASIZE];
-} PyDateTime_DateTime;
+       PyObject_HEAD           /* a pure abstract base clase */
+} PyDateTime_TZInfo;
 
 typedef struct
 {
        PyObject_HEAD
        long hashcode;
-       unsigned char data[_PyDateTime_DATETIME_DATASIZE];
-       PyObject *tzinfo;
-} PyDateTime_DateTimeTZ;
+       unsigned char data[_PyDateTime_DATE_DATASIZE];
+} PyDateTime_Date;
 
 
+/* The datetime and time types have hashcodes, and an optional tzinfo member,
+ * present if and only if hastzinfo is true.
+ */
+#define _PyTZINFO_HEAD         \
+       PyObject_HEAD           \
+       long hashcode;          \
+       char hastzinfo;         /* boolean flag */
 
+/* No _PyDateTime_BaseTZInfo is allocated; it's just to have something
+ * convenient to cast to, when getting at the hastzinfo member of objects
+ * starting with _PyTZINFO_HEAD.
+ */
+typedef struct
+{
+       _PyTZINFO_HEAD
+} _PyDateTime_BaseTZInfo;
+
+/* All time objects are of PyDateTime_TimeType, but that can be allocated
+ * in two ways, with or without a tzinfo member.  Without is the same as
+ * tzinfo == None, but consumes less memory.  _PyDateTime_BaseTime is an
+ * internal struct used to allocate the right amount of space for the
+ * "without" case.
+ */
 #define _PyDateTime_TIMEHEAD   \
        _PyTZINFO_HEAD          \
        unsigned char data[_PyDateTime_TIME_DATASIZE];
@@ -71,20 +88,23 @@ typedef struct
        PyObject *tzinfo;
 } PyDateTime_Time;             /* hastzinfo true */
 
+/* XXX The date type will be reworked similarly. */
 
 typedef struct
 {
        PyObject_HEAD
-       long hashcode;          /* -1 when unknown */
-       int days;               /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
-       int seconds;            /* 0 <= seconds < 24*3600 is invariant */
-       int microseconds;       /* 0 <= microseconds < 1000000 is invariant */
-} PyDateTime_Delta;
+       long hashcode;
+       unsigned char data[_PyDateTime_DATETIME_DATASIZE];
+} PyDateTime_DateTime;
 
 typedef struct
 {
-       PyObject_HEAD           /* a pure abstract base clase */
-} PyDateTime_TZInfo;
+       PyObject_HEAD
+       long hashcode;
+       unsigned char data[_PyDateTime_DATETIME_DATASIZE];
+       PyObject *tzinfo;
+} PyDateTime_DateTimeTZ;
+
 
 /* Apply for date, datetime, and datetimetz instances. */
 #define PyDateTime_GET_YEAR(o)     ((((PyDateTime_Date*)o)->data[0] << 8) | \
index b8503d238375b43c4601f0029ca4ea765b7bed6d..973034bfe19871c5738c51bef031a73ef47cb57f 100644 (file)
 #define SET_TD_SECONDS(o, v)   ((o)->seconds = (v))
 #define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
 
+/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns
+ * p->hastzinfo.
+ */
+#define HASTZINFO(p)           (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo)
+
 /* Forward declarations. */
 static PyTypeObject PyDateTime_DateType;
 static PyTypeObject PyDateTime_DateTimeType;
@@ -606,7 +611,7 @@ get_tzinfo_member(PyObject *self)
 
        if (PyDateTimeTZ_Check(self))
                tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
-       else if (PyTime_Check(self) && ((PyDateTime_Time *)self)->hastzinfo)
+       else if (PyTime_Check(self) && HASTZINFO(self))
                tzinfo = ((PyDateTime_Time *)self)->tzinfo;
 
        return tzinfo;
@@ -2966,9 +2971,7 @@ datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
                                                TIME_GET_MINUTE(time),
                                                TIME_GET_SECOND(time),
                                                TIME_GET_MICROSECOND(time));
-       if (result &&
-           ((PyDateTime_Time *)time)->hastzinfo &&
-           PyDateTimeTZ_Check(result)) {
+       if (result && HASTZINFO(time) && PyDateTimeTZ_Check(result)) {
                /* Copy the tzinfo field. */
                replace_tzinfo(result, ((PyDateTime_Time *)time)->tzinfo);
        }
@@ -3618,7 +3621,7 @@ time_microsecond(PyDateTime_Time *self, void *unused)
 static PyObject *
 time_tzinfo(PyDateTime_Time *self, void *unused)
 {
-       PyObject *result = self->hastzinfo ? self->tzinfo : Py_None;
+       PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
        Py_INCREF(result);
        return result;
 }
@@ -3668,7 +3671,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
 static void
 time_dealloc(PyDateTime_Time *self)
 {
-       if (self->hastzinfo) {
+       if (HASTZINFO(self)) {
                Py_XDECREF(self->tzinfo);
        }
        self->ob_type->tp_free((PyObject *)self);
@@ -3681,19 +3684,19 @@ time_dealloc(PyDateTime_Time *self)
 /* These are all METH_NOARGS, so don't need to check the arglist. */
 static PyObject *
 time_utcoffset(PyDateTime_Time *self, PyObject *unused) {
-       return offset_as_timedelta(self->hastzinfo ? self->tzinfo : Py_None,
+       return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
                                   "utcoffset", Py_None);
 }
 
 static PyObject *
 time_dst(PyDateTime_Time *self, PyObject *unused) {
-       return offset_as_timedelta(self->hastzinfo ? self->tzinfo : Py_None,
+       return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
                                   "dst", Py_None);
 }
 
 static PyObject *
 time_tzname(PyDateTime_Time *self, PyObject *unused) {
-       return call_tzname(self->hastzinfo ? self->tzinfo : Py_None,
+       return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
                           Py_None);
 }
 
@@ -3722,7 +3725,7 @@ time_repr(PyDateTime_Time *self)
                PyOS_snprintf(buffer, sizeof(buffer),
                              "%s(%d, %d)", typename, h, m);
        result = PyString_FromString(buffer);
-       if (result != NULL && self->hastzinfo)
+       if (result != NULL && HASTZINFO(self))
                result = append_keyword_tzinfo(result, self->tzinfo);
        return result;
 }
@@ -3749,7 +3752,7 @@ time_isoformat(PyDateTime_Time *self)
 
        isoformat_time(pdatetime, buf, sizeof(buf));
        result = PyString_FromString(buf);
-       if (result == NULL || ! self->hastzinfo || self->tzinfo == Py_None)
+       if (result == NULL || ! HASTZINFO(self) || self->tzinfo == Py_None)
                return result;
 
        /* We need to append the UTC offset. */
@@ -3876,7 +3879,7 @@ time_hash(PyDateTime_Time *self)
                        int minute;
 
                        assert(n == OFFSET_AWARE);
-                       assert(self->hastzinfo);
+                       assert(HASTZINFO(self));
                        hour = divmod(TIME_GET_HOUR(self) * 60 +
                                        TIME_GET_MINUTE(self) - offset,
                                      60,
@@ -3909,7 +3912,7 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
        int mm = TIME_GET_MINUTE(self);
        int ss = TIME_GET_SECOND(self);
        int us = TIME_GET_MICROSECOND(self);
-       PyObject *tzinfo = self->hastzinfo ? self->tzinfo : Py_None;
+       PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
 
        if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
                                          time_kws,
@@ -3936,7 +3939,7 @@ time_nonzero(PyDateTime_Time *self)
                return 1;
        }
        offset = 0;
-       if (self->hastzinfo && self->tzinfo != Py_None) {
+       if (HASTZINFO(self) && self->tzinfo != Py_None) {
                offset = call_utcoffset(self->tzinfo, Py_None, &none);
                if (offset == -1 && PyErr_Occurred())
                        return -1;
@@ -3961,7 +3964,7 @@ time_getstate(PyDateTime_Time *self)
        basestate =  PyString_FromStringAndSize((char *)self->data,
                                                _PyDateTime_TIME_DATASIZE);
        if (basestate != NULL) {
-               if (! self->hastzinfo || self->tzinfo == Py_None)
+               if (! HASTZINFO(self) || self->tzinfo == Py_None)
                        result = Py_BuildValue("(O)", basestate);
                else
                        result = Py_BuildValue("OO", basestate, self->tzinfo);
@@ -3986,7 +3989,7 @@ time_setstate(PyDateTime_Time *self, PyObject *state)
                                "bad argument to time.__setstate__");
                return NULL;
        }
-       if (tzinfo != Py_None && ! self->hastzinfo) {
+       if (tzinfo != Py_None && ! HASTZINFO(self)) {
                PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
                                "add a non-None tzinfo to a time object that "
                                "doesn't have one already");
@@ -3996,7 +3999,7 @@ time_setstate(PyDateTime_Time *self, PyObject *state)
               PyString_AsString(basestate),
               _PyDateTime_TIME_DATASIZE);
        self->hashcode = -1;
-       if (self->hastzinfo) {
+       if (HASTZINFO(self)) {
                Py_INCREF(tzinfo);
                Py_XDECREF(self->tzinfo);
                self->tzinfo = tzinfo;