static void icaltimezone_expand_changes (icaltimezone *zone, int end_year) { icalarray *changes; icalcomponent *comp; #if 0 printf ("\nExpanding changes for: %s to year: %i\n", zone->tzid, end_year); #endif changes = icalarray_new (sizeof (icaltimezonechange), 32); if (!changes) return; /* Scan the STANDARD and DAYLIGHT subcomponents. */ comp = icalcomponent_get_first_component (zone->component, ICAL_ANY_COMPONENT); while (comp) { icaltimezone_expand_vtimezone (comp, end_year, changes); comp = icalcomponent_get_next_component (zone->component, ICAL_ANY_COMPONENT); } /* Sort the changes. We may have duplicates but I don't think it will matter. */ icalarray_sort (changes, icaltimezone_compare_change_fn); if (zone->changes) icalarray_free (zone->changes); zone->changes = changes; zone->end_year = end_year; }
icalarray *icalarray_copy (icalarray *originalarray) { icalarray *array = icalarray_new(originalarray->element_size, originalarray->increment_size); int chunks = originalarray->space_allocated / originalarray->increment_size; int chunk; if (!array) return NULL; array->num_elements = originalarray->num_elements; array->space_allocated = originalarray->space_allocated; array->chunks = malloc(chunks * sizeof (void *)); if (array->chunks) { for (chunk = 0; chunk < chunks; chunk++) { array->chunks[chunk] = icalarray_alloc_chunk(array); if (array->chunks[chunk]) memcpy(array->chunks[chunk], originalarray->chunks[chunk], array->increment_size * array->element_size); } } else { icalerror_set_errno(ICAL_ALLOCATION_ERROR); } return array; }
/** This parses the zones.tab file containing the names and locations of the builtin timezones. It creates the builtin_timezones array which is an icalarray of icaltimezone structs. It only fills in the location, latitude and longtude fields; the rest are left blank. The VTIMEZONE component is loaded later if it is needed. The timezones in the zones.tab file are sorted by their name, which is useful for binary searches. */ static void icaltimezone_parse_zone_tab (void) { char *filename; FILE *fp; char buf[1024]; /* Used to store each line of zones.tab as it is read. */ char location[1024]; /* Stores the city name when parsing buf. */ unsigned int filename_len; int latitude_degrees, latitude_minutes, latitude_seconds; int longitude_degrees, longitude_minutes, longitude_seconds; icaltimezone zone; icalerror_assert (builtin_timezones == NULL, "Parsing zones.tab file multiple times"); builtin_timezones = icalarray_new (sizeof (icaltimezone), 32); filename_len = strlen (get_zone_directory()) + strlen (ZONES_TAB_FILENAME) + 2; filename = (char*) malloc (filename_len); if (!filename) { icalerror_set_errno(ICAL_NEWFAILED_ERROR); return; } snprintf (filename, filename_len, "%s/%s", get_zone_directory(), ZONES_TAB_FILENAME); fp = fopen (filename, "r"); free (filename); if (!fp) { icalerror_set_errno(ICAL_FILE_ERROR); return; } while (fgets (buf, sizeof(buf), fp)) { if (*buf == '#') continue; /* The format of each line is: "latitude longitude location". */ if (sscanf (buf, "%4d%2d%2d %4d%2d%2d %s", &latitude_degrees, &latitude_minutes, &latitude_seconds, &longitude_degrees, &longitude_minutes, &longitude_seconds, location) != 7) { fprintf (stderr, "Invalid timezone description line: %s\n", buf); continue; } icaltimezone_init (&zone); zone.location = strdup (location); if (latitude_degrees >= 0) zone.latitude = (double) latitude_degrees + (double) latitude_minutes / 60 + (double) latitude_seconds / 3600; else zone.latitude = (double) latitude_degrees - (double) latitude_minutes / 60 - (double) latitude_seconds / 3600; if (longitude_degrees >= 0) zone.longitude = (double) longitude_degrees + (double) longitude_minutes / 60 + (double) longitude_seconds / 3600; else zone.longitude = (double) longitude_degrees - (double) longitude_minutes / 60 - (double) longitude_seconds / 3600; icalarray_append (builtin_timezones, &zone); #if 0 printf ("Found zone: %s %f %f\n", location, zone.latitude, zone.longitude); #endif free (zone.location); } fclose (fp); }
icalarray* icaltimezone_array_new (void) { return icalarray_new (sizeof (icaltimezone), 16); }