[glib] Win32 TimeZone Support: General refactoring



commit d12bb7ef7284b49ccdeb81d7ef80b572eb1195d8
Author: John Ralls <jralls ceridwen us>
Date:   Tue Dec 4 10:51:48 2012 -0800

    Win32 TimeZone Support: General refactoring
    
    For code clarity and to pass tests

 glib/gtimezone.c |  530 ++++++++++++++++++++++++++----------------------------
 1 files changed, 259 insertions(+), 271 deletions(-)
---
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
index 118b3f3..028d40a 100644
--- a/glib/gtimezone.c
+++ b/glib/gtimezone.c
@@ -151,6 +151,12 @@ typedef struct
   gboolean isgmt;
 } TimeZoneDate;
 
+/* POSIX Timezone abbreviations are typically 3 or 4 characters, but
+   Microsoft uses 32-character names. We'll use one larger to ensure
+   we have room for the terminating \0.
+ */
+#define NAME_SIZE 33
+
 typedef struct
 {
   gint         start_year;
@@ -158,8 +164,8 @@ typedef struct
   gint32       dlt_offset;
   TimeZoneDate dlt_start;
   TimeZoneDate dlt_end;
-  const gchar *std_name;
-  const gchar *dlt_name;
+  gchar std_name[NAME_SIZE];
+  gchar dlt_name[NAME_SIZE];
 } TimeZoneRule;
 
 
@@ -213,7 +219,8 @@ again:
           G_UNLOCK(time_zones);
         }
 
-      g_array_free (tz->t_info, TRUE);
+      if (tz->t_info != NULL)
+        g_array_free (tz->t_info, TRUE);
       if (tz->transitions != NULL)
         g_array_free (tz->transitions, TRUE);
       g_free (tz->name);
@@ -495,129 +502,141 @@ init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
 
 #elif defined (G_OS_WIN32)
 
+static void
+copy_windows_systemtime (SYSTEMTIME *s_time, TimeZoneDate *tzdate)
+{
+  tzdate->sec = s_time->wSecond;
+  tzdate->min = s_time->wMinute;
+  tzdate->hour = s_time->wHour;
+  tzdate->mon = s_time->wMonth;
+  tzdate->year = s_time->wYear;
+  tzdate->wday = s_time->wDayOfWeek ? s_time->wDayOfWeek : 7;
+
+  if (s_time->wYear)
+    {
+      tzdate->mday = s_time->wDay;
+      tzdate->wday = 0;
+    }
+  else
+    tzdate->week = s_time->wDay;
+}
+
 /* UTC = local time + bias while local time = UTC + offset */
 static void
-rule_from_windows_time_zone_info (TimeZoneRule *rules,
-                                  LONG          Bias,
-                                  LONG          StandardBias,
-                                  LONG          DaylightBias,
-                                  SYSTEMTIME    StandardDate,
-                                  SYSTEMTIME    DaylightDate)
+rule_from_windows_time_zone_info (TimeZoneRule *rule,
+                                  TIME_ZONE_INFORMATION *tzi)
 {
   /* Set offset */
-  if (StandardDate.wMonth)
+  if (tzi->StandardDate.wMonth)
     {
-      rules->std_offset = -(Bias + StandardBias) * 60;
-      rules->dlt_offset = -(Bias + DaylightBias) * 60;
-
-      rules->dlt_start.sec = DaylightDate.wSecond;
-      rules->dlt_start.min = DaylightDate.wMinute;
-      rules->dlt_start.hour = DaylightDate.wHour;
-      rules->dlt_start.mon = DaylightDate.wMonth;
-      rules->dlt_start.year = DaylightDate.wYear;
-      rules->dlt_start.wday = DaylightDate.wDayOfWeek? DaylightDate.wDayOfWeek : 7;
+      rule->std_offset = -(tzi->Bias + tzi->StandardBias) * 60;
+      rule->dlt_offset = -(tzi->Bias + tzi->DaylightBias) * 60;
+      copy_windows_systemtime (&(tzi->DaylightDate), &(rule->dlt_start));
 
-      if (DaylightDate.wYear)
-        {
-          rules->dlt_start.mday = DaylightDate.wDay;
-          rules->dlt_start.wday = 0;
-        }
-      else
-        rules->dlt_start.week = DaylightDate.wDay;
+      rule->dlt_start.isstd = FALSE;
+      rule->dlt_start.isgmt = FALSE;
+      copy_windows_systemtime (&(tzi->StandardDate), &(rule->dlt_end));
 
-      rules->dlt_start.isstd = FALSE;
-      rules->dlt_start.isgmt = FALSE;
+      rule->dlt_end.isstd = FALSE;
+      rule->dlt_end.isgmt = FALSE;
+    }
 
-      rules->dlt_end.sec = StandardDate.wSecond;
-      rules->dlt_end.min = StandardDate.wMinute;
-      rules->dlt_end.hour = StandardDate.wHour;
-      rules->dlt_end.mday = StandardDate.wDay;
-      rules->dlt_end.mon = StandardDate.wMonth;
-      rules->dlt_end.year = StandardDate.wYear;
-      rules->dlt_end.wday = StandardDate.wDayOfWeek? StandardDate.wDayOfWeek : 7;
+  else
+    {
+      rule->std_offset = -tzi->Bias * 60;
+      rule->dlt_start.mon = 0;
+    }
+}
 
-      if (StandardDate.wYear)
+static gchar*
+windows_default_tzname (void)
+{
+  const gchar *subkey =
+    "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
+  HKEY key;
+  gchar *key_name = NULL;
+  if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
+                     KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
+    {
+      DWORD size = 0;
+      if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
+                            NULL, &size) == ERROR_SUCCESS)
         {
-          rules->dlt_end.mday = StandardDate.wDay;
-          rules->dlt_end.wday = 0;
+          key_name = g_malloc ((gint)size);
+          if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
+                                (LPBYTE)key_name, &size) != ERROR_SUCCESS)
+            {
+              g_free (key_name);
+              key_name = NULL;
+            }
         }
-      else
-        rules->dlt_end.week = StandardDate.wDay;
-
-      rules->dlt_end.isstd = FALSE;
-      rules->dlt_end.isgmt = FALSE;
+      RegCloseKey (key);
     }
+  return key_name;
+}
 
-  else
-    {
-      rules->std_offset = -Bias * 60;
+typedef   struct
+{
+  LONG Bias;
+  LONG StandardBias;
+  LONG DaylightBias;
+  SYSTEMTIME StandardDate;
+  SYSTEMTIME DaylightDate;
+} RegTZI;
 
-      rules->dlt_start.mon = 0;
-    }
+static void
+system_time_copy (SYSTEMTIME *orig, SYSTEMTIME *target)
+{
+  g_return_if_fail (orig != NULL);
+  g_return_if_fail (target != NULL);
+
+  target->wYear = orig->wYear;
+  target->wMonth = orig->wMonth;
+  target->wDayOfWeek = orig->wDayOfWeek;
+  target->wDay = orig->wDay;
+  target->wHour = orig->wHour;
+  target->wMinute = orig->wMinute;
+  target->wSecond = orig->wSecond;
+  target->wMilliseconds = orig->wMilliseconds;
 }
 
-static gboolean
-rules_from_windows_time_zone (const gchar   *identifier,
-                              TimeZoneRule **rules,
-                              gint          *rules_num,
-                              gchar        **std_name,
-                              gchar        **dlt_name)
+static void
+register_tzi_to_tzi (RegTZI *reg, TIME_ZONE_INFORMATION *tzi)
+{
+  g_return_if_fail (reg != NULL);
+  g_return_if_fail (tzi != NULL);
+  tzi->Bias = reg->Bias;
+  system_time_copy (&(reg->StandardDate), &(tzi->StandardDate));
+  tzi->StandardBias = reg->StandardBias;
+  system_time_copy (&(reg->DaylightDate), &(tzi->DaylightDate));
+  tzi->DaylightBias = reg->DaylightBias;
+}
+
+static gint
+rules_from_windows_time_zone (const gchar *identifier, TimeZoneRule **rules)
 {
   HKEY key;
   gchar *subkey, *subkey_dynamic;
-  gchar *key_name;
-
-  /* REG_TZI_FORMAT */
-  struct {
-    LONG Bias;
-    LONG StandardBias;
-    LONG DaylightBias;
-    SYSTEMTIME StandardDate;
-    SYSTEMTIME DaylightDate;
-  } tzi, tzi_prev;
+  gchar *key_name = NULL;
+  const gchar *reg_key =
+    "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\";
+  TIME_ZONE_INFORMATION tzi;
   DWORD size;
+  gint rules_num = 0;
+  RegTZI regtzi, regtzi_prev;
 
   *rules = NULL;
-  *rules_num = 0;
-  *std_name = NULL;
-  *dlt_name = NULL;
-
   key_name = NULL;
 
   if (!identifier)
-    {
-      subkey = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
-
-      if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
-                         KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
-        {
-          size = 0;
-          if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
-                                NULL, &size) == ERROR_SUCCESS)
-            {
-              key_name = g_malloc (size);
-
-              if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
-                                    (LPBYTE) key_name, &size) != ERROR_SUCCESS)
-                {
-                  g_free (key_name);
-                  key_name = NULL;
-                }
-            }
-
-          RegCloseKey (key);
-        }
-    }
+    key_name = windows_default_tzname ();
   else
     key_name = g_strdup (identifier);
 
   if (!key_name)
-    return FALSE;
-
-  subkey = g_strconcat ("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\",
-                        key_name,
-                        NULL);
+    return 0;
 
+  subkey = g_strconcat (reg_key, key_name, NULL);
   subkey_dynamic = g_strconcat (subkey, "\\Dynamic DST", NULL);
 
   if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey_dynamic, 0,
@@ -637,16 +656,16 @@ rules_from_windows_time_zone (const gchar   *identifier,
                             (LPBYTE) &last, &size) != ERROR_SUCCESS)
         goto failed;
 
-      *rules_num = last - first + 2;
-      *rules = g_new0 (TimeZoneRule, *rules_num);
+      rules_num = last - first + 2;
+      *rules = g_new0 (TimeZoneRule, rules_num);
 
       for (year = first, i = 0; year <= last; year++)
         {
           s = g_strdup_printf ("%d", year);
 
-          size = sizeof tzi;
+          size = sizeof regtzi;
           if (RegQueryValueExA (key, s, NULL, NULL,
-                            (LPBYTE) &tzi, &size) != ERROR_SUCCESS)
+                            (LPBYTE) &regtzi, &size) != ERROR_SUCCESS)
             {
               g_free (*rules);
               *rules = NULL;
@@ -655,19 +674,17 @@ rules_from_windows_time_zone (const gchar   *identifier,
 
           g_free (s);
 
-          if (year > first && memcmp (&tzi_prev, &tzi, sizeof tzi) == 0)
+          if (year > first && memcmp (&regtzi_prev, &regtzi, sizeof regtzi) == 0)
               continue;
           else
-            memcpy (&tzi_prev, &tzi, sizeof tzi);
-
-          rule_from_windows_time_zone_info (&(*rules)[i], tzi.Bias,
-                                            tzi.StandardBias, tzi.DaylightBias,
-                                            tzi.StandardDate, tzi.DaylightDate);
+            memcpy (&regtzi_prev, &regtzi, sizeof regtzi);
 
+          register_tzi_to_tzi (&regtzi, &tzi); 
+          rule_from_windows_time_zone_info (&(*rules)[i], &tzi);
           (*rules)[i++].start_year = year;
         }
 
-      *rules_num = i + 1;
+      rules_num = i + 1;
 
 failed:
       RegCloseKey (key);
@@ -675,16 +692,14 @@ failed:
   else if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
                           KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
     {
-      size = sizeof tzi;
+      size = sizeof regtzi;
       if (RegQueryValueExA (key, "TZI", NULL, NULL,
-                            (LPBYTE) &tzi, &size) == ERROR_SUCCESS)
+                            (LPBYTE) &regtzi, &size) == ERROR_SUCCESS)
         {
-          *rules_num = 2;
+          rules_num = 2;
           *rules = g_new0 (TimeZoneRule, 2);
-
-          rule_from_windows_time_zone_info (&(*rules)[0], tzi.Bias,
-                                            tzi.StandardBias, tzi.DaylightBias,
-                                            tzi.StandardDate, tzi.DaylightDate);
+          register_tzi_to_tzi (&regtzi, &tzi);
+          rule_from_windows_time_zone_info (&(*rules)[0], &tzi);
         }
 
       RegCloseKey (key);
@@ -697,15 +712,15 @@ failed:
   if (*rules)
     {
       (*rules)[0].start_year = MIN_TZYEAR;
-      if ((*rules)[*rules_num - 2].start_year < MAX_TZYEAR)
-        (*rules)[*rules_num - 1].start_year = MAX_TZYEAR;
+      if ((*rules)[rules_num - 2].start_year < MAX_TZYEAR)
+        (*rules)[rules_num - 1].start_year = MAX_TZYEAR;
       else
-        (*rules)[*rules_num - 1].start_year = (*rules)[*rules_num - 2].start_year + 1;
+        (*rules)[rules_num - 1].start_year = (*rules)[rules_num - 2].start_year + 1;
 
-      return TRUE;
+      return rules_num;
     }
   else
-    return FALSE;
+    return 0;
 }
 
 #endif
@@ -1101,197 +1116,181 @@ parse_tz_boundary (const gchar  *identifier,
     }
 }
 
-/*
- * Creates an array of TimeZoneRule from a TZ environment variable
- * type of identifier.  Should free rules, std_name and dlt_name
- * afterwards
- */
-static gboolean
-rules_from_identifier (const gchar   *identifier,
-                       TimeZoneRule **rules,
-                       gint          *rules_num,
-                       gchar        **std_name,
-                       gchar        **dlt_name)
+static gint
+create_ruleset_from_rule (TimeZoneRule **rules, TimeZoneRule *rule)
 {
-  const gchar *std_name_pos, *std_offset_pos;
-  const gchar *dlt_name_pos, *dlt_offset_pos;
+  *rules = g_new0 (TimeZoneRule, 2);
 
-  const gchar *start_date_pos, *end_date_pos;
+  (*rules)[0].start_year = MIN_TZYEAR;
+  (*rules)[1].start_year = MAX_TZYEAR;
 
-  const gchar *pos;
+  (*rules)[0].std_offset = -rule->std_offset;
+  (*rules)[0].dlt_offset = -rule->dlt_offset;
+  (*rules)[0].dlt_start  = rule->dlt_start;
+  (*rules)[0].dlt_end = rule->dlt_end;
+  strcpy (rule->std_name, (*rules)[0].std_name);
+  strcpy (rule->dlt_name, (*rules)[0].dlt_name);
+  return 2;
+}
+
+static gboolean
+parse_offset (gchar **pos, gint32 *target)
+{
   gchar *buffer;
+  gchar *target_pos = *pos;
   gboolean ret;
 
-  gint32 std_offset, dlt_offset;
-  TimeZoneDate dlt_start, dlt_end;
+  while (**pos == '+' || **pos == '-' || **pos == ':' ||
+         (**pos >= '0' && '9' >= **pos))
+    ++(*pos);
 
-  if (!identifier)
-    return FALSE;
+  buffer = g_strndup (target_pos, *pos - target_pos);
+  ret = parse_constant_offset (buffer, target);
+  g_free (buffer);
 
-  pos = identifier;
+  return ret;
+}
 
-  std_name_pos = pos;
+static gboolean
+parse_identifier_boundary (gchar **pos, TimeZoneDate *target)
+{
+  gchar *buffer;
+  gchar *target_pos = *pos;
+  gboolean ret;
+
+  while (**pos != ',' && **pos != '\0')
+    ++(*pos);
+  buffer = g_strndup (target_pos, *pos++ - target_pos);
+  ret = parse_tz_boundary (buffer, target);
+  g_free (buffer);
 
-  /* Name is alpha */
-  while ((*pos >= 'a' && 'z' >= *pos) || (*pos >= 'A' && 'Z' >= *pos))
-    pos++;
+  return ret;
+}
+
+static boolean
+set_tz_name (gchar **pos, gchar *buffer, guint size)
+{
+  gchar *name_pos = *pos;
+  guint len;
+
+  /* Name is ASCII alpha (Is this necessarily true?) */
+  while (g_ascii_isalpha (**pos))
+    ++(*pos);
 
   /* Offset for standard required (format 1) */
-  if (*pos == '\0')
+  if (**pos == '\0')
     return FALSE;
 
   /* Name should be three or more alphabetic characters */
-  if (pos - identifier < 3)
+  if (*pos - name_pos < 3)
     return FALSE;
 
-  std_offset_pos = pos;
+  memset (buffer, 0, NAME_SIZE);
+  /* name_pos isn't 0-terminated, so we have to limit the length expressly */
+  len = *pos - name_pos > size - 1 ? size - 1 : *pos - name_pos;
+  strncpy (buffer, name_pos, len); 
+  return TRUE;
+}
 
-  /* Standard offset */
-  while (*pos == '+' || *pos == '-' || *pos == ':' || (*pos >= '0' && '9' >= *pos))
-    pos++;
+static gboolean
+parse_identifier_boundaries (gchar **pos, TimeZoneRule *tzr)
+{
+  /* Default offset is 1 hour less from standard offset */
+  if (*(*pos++) == ',')
+    {
+      tzr->dlt_offset = tzr->std_offset - 60 * 60;
+      return TRUE;
+    }
+  /* Daylight offset */
+  if (!parse_offset (pos, &(tzr->dlt_offset)))
+      return FALSE;
 
-  buffer = g_strndup (std_offset_pos, pos - std_offset_pos);
-  ret = parse_constant_offset (buffer, &std_offset);
-  g_free (buffer);
+      /* Start and end required (format 2) */
+  if (*(*pos++) != ',')
+    return FALSE;
+
+  /* Start date */
+  if (!parse_identifier_boundary (pos, &(tzr->dlt_start)) || **pos != ',')
+    return FALSE;
 
-  if (!ret)
+  /* End date */
+  if (!parse_identifier_boundary (pos, &(tzr->dlt_end)))
     return FALSE;
+  return TRUE;
+}
+
+/*
+ * Creates an array of TimeZoneRule from a TZ environment variable
+ * type of identifier.  Should free rules afterwards
+ */
+static gint
+rules_from_identifier (const gchar   *identifier,
+                       TimeZoneRule **rules)
+{
+  gchar *pos;
+  TimeZoneRule tzr;
 
-  dlt_name_pos = pos;
-  dlt_offset_pos = NULL;
+  if (!identifier)
+    return 0;
+
+  pos = (gchar*)identifier;
+  memset (&tzr, 0, sizeof (tzr));
+  /* Standard offset */
+  if (!(set_tz_name (&pos, tzr.std_name, NAME_SIZE)) ||
+      !parse_offset (&pos, &(tzr.std_offset)))
+    return 0;
 
   /* Format 2 */
   if (*pos != '\0')
     {
-      /* Name is alpha */
-      while ((*pos >= 'a' && 'z' >= *pos) || (*pos >= 'A' && 'Z' >= *pos))
-        pos++;
-
-      /* Name should be three or more alphabetic characters */
-      if (pos - identifier < 3)
-        return FALSE;
-
-      dlt_offset_pos = pos;
+      if (!(set_tz_name (&pos, tzr.dlt_name, NAME_SIZE)))
+        return 0;
 
 #ifndef G_OS_WIN32
       /* Start and end required (format 2) */
       if (*pos == '\0')
-        return FALSE;
+        return 0;
 #else
       if (*pos != '\0')
         {
 #endif
-
-      /* Default offset is 1 hour less from standard offset */
-      if (*pos++ == ',')
-        dlt_offset = std_offset - 60 * 60;
-
-      else
-        {
-          /* Daylight offset */
-          while (*pos == '+' || *pos == '-' || *pos == ':' || (*pos >= '0' && '9' >= *pos))
-            pos++;
-
-          buffer = g_strndup (dlt_offset_pos, pos - dlt_offset_pos);
-          ret = parse_constant_offset (buffer, &dlt_offset);
-          g_free (buffer);
-
-          if (!ret)
-            return FALSE;
-
-          /* Start and end required (format 2) */
-          if (*pos++ != ',')
-            return FALSE;
-        }
-
-      /* Start date */
-      start_date_pos = pos;
-
-      while (*pos != ',' && *pos != '\0')
-        pos++;
-
-      /* End required (format 2) */
-      if (*pos == '\0')
-        return FALSE;
-
-      buffer = g_strndup (start_date_pos, pos++ - start_date_pos);
-      ret = parse_tz_boundary (buffer, &dlt_start);
-      g_free (buffer);
-
-      if (!ret)
-        return FALSE;
-
-      /* End date */
-      end_date_pos = pos;
-
-      while (*pos != '\0')
-        pos++;
-
-      buffer = g_strndup (end_date_pos, pos - end_date_pos);
-      ret = parse_tz_boundary (buffer, &dlt_end);
-      g_free (buffer);
-
-      if (!ret)
-        return FALSE;
-
+          if (!parse_identifier_boundaries (&pos, &tzr))
+              return 0;
+ 
 #ifdef G_OS_WIN32
       }
 #endif
     }
 
-
-  *std_name = g_strndup (std_name_pos, std_offset_pos - std_name_pos);
-
-  if (dlt_name_pos != pos)
-    *dlt_name = g_strndup (dlt_name_pos, dlt_offset_pos - dlt_name_pos);
-  else
-    {
-      *dlt_name = NULL;
-      dlt_start.mon = 0;
-    }
-
-
 #ifdef G_OS_WIN32
   /* If doesn't have offset for daylight then it is Windows format */
-  if (dlt_offset_pos == pos)
+  if (tzr.dlt_offset == 0)
     {
       int i;
+      guint rules_num = 0;
 
       /* Use US rules, Windows' default is Pacific Standard Time */
-      dlt_offset = std_offset - 60 * 60;
+      tzr.dlt_offset = tzr.std_offset - 60 * 60;
 
-      if (rules_from_windows_time_zone ("Pacific Standard Time", rules, rules_num, NULL, NULL))
+      if ((rules_num = rules_from_windows_time_zone ("Pacific Standard Time",
+                                                     rules)))
         {
-          for (i = 0; i < *rules_num - 1; i++)
+          for (i = 0; i < rules_num - 1; i++)
             {
-              (*rules)[i].std_offset = -std_offset;
-              (*rules)[i].dlt_offset = -dlt_offset;
-              (*rules)[i].std_name = *std_name;
-              (*rules)[i].dlt_name = *dlt_name;
+              (*rules)[i].std_offset = - tzr.std_offset;
+              (*rules)[i].dlt_offset = - tzr.dlt_offset;
+              strcpy ((*rules)[i].std_name, tzr.std_name);
+              strcpy ((*rules)[i].dlt_name, tzr.dlt_name);
             }
 
-          return TRUE;
+          return rules_num;
         }
       else
-        return FALSE;
+        return 0;
     }
 #endif
 
-
-  *rules_num = 2;
-  *rules = g_new0 (TimeZoneRule, 2);
-
-  (*rules)[0].start_year = MIN_TZYEAR;
-  (*rules)[1].start_year = MAX_TZYEAR;
-
-  (*rules)[0].std_offset = -std_offset;
-  (*rules)[0].dlt_offset = -dlt_offset;
-  (*rules)[0].dlt_start  = dlt_start;
-  (*rules)[0].dlt_end = dlt_end;
-  (*rules)[0].std_name = *std_name;
-  (*rules)[0].dlt_name = *dlt_name;
-
-  return TRUE;
+  return create_ruleset_from_rule (rules, &tzr);
 }
 
 /* Construction {{{1 */
@@ -1375,7 +1374,6 @@ g_time_zone_new (const gchar *identifier)
   GTimeZone *tz = NULL;
   TimeZoneRule *rules;
   gint rules_num;
-  gchar *std_name, *dlt_name;
 
   G_LOCK (time_zones);
   if (time_zones == NULL)
@@ -1399,14 +1397,10 @@ g_time_zone_new (const gchar *identifier)
   zone_for_constant_offset (tz, identifier);
 
   if (tz->t_info == NULL &&
-      rules_from_identifier (identifier,
-                             &rules, &rules_num,
-                             &std_name, &dlt_name))
+      (rules_num = rules_from_identifier (identifier, &rules)))
     {
       init_zone_from_rules (tz, rules, rules_num);
       g_free (rules);
-      g_free (std_name);
-      g_free (dlt_name);
     }
 
   if (tz->t_info == NULL)
@@ -1421,14 +1415,10 @@ g_time_zone_new (const gchar *identifier)
           g_bytes_unref (zoneinfo);
         }
 #elif defined (G_OS_WIN32)
-      if (rules_from_windows_time_zone (identifier,
-                                        &rules, &rules_num,
-                                        &std_name, &dlt_name))
+      if ((rules_num = rules_from_windows_time_zone (identifier, &rules)))
         {
           init_zone_from_rules (tz, rules, rules_num);
           g_free (rules);
-          g_free (std_name);
-          g_free (dlt_name);
         }
     }
 
@@ -1444,12 +1434,10 @@ g_time_zone_new (const gchar *identifier)
             {
               rules = g_new0 (TimeZoneRule, 2);
 
-              rule_from_windows_time_zone_info (&rules[0], tzi.Bias,
-                                                tzi.StandardBias, tzi.DaylightBias,
-                                                tzi.StandardDate, tzi.DaylightDate);
+              rule_from_windows_time_zone_info (&rules[0], &tzi);
 
-              rules[0].std_name = NULL;
-              rules[0].dlt_name = NULL;
+              memset (rules[0].std_name, 0, NAME_SIZE);
+              memset (rules[0].dlt_name, 0, NAME_SIZE);
 
               rules[0].start_year = MIN_TZYEAR;
               rules[1].start_year = MAX_TZYEAR;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]