Ejemplo n.º 1
0
/**
 * g_time_zone_unref:
 * @tz: a #GTimeZone
 *
 * Decreases the reference count on @tz.
 *
 * Since: 2.26
 **/
void
g_time_zone_unref (GTimeZone *tz)
{
  g_assert (tz->ref_count > 0);

  if (g_atomic_int_dec_and_test (&tz->ref_count))
    {
      G_LOCK(time_zones);
      g_hash_table_remove (time_zones, tz->name);
      G_UNLOCK(time_zones);

      if (tz->zoneinfo)
        g_buffer_unref (tz->zoneinfo);

      g_free (tz->name);

      g_slice_free (GTimeZone, tz);
    }
}
Ejemplo n.º 2
0
/**
 * g_variant_unref:
 * @value: a #GVariant
 *
 * Decreases the reference count of @value.  When its reference count
 * drops to 0, the memory used by the variant is freed.
 *
 * Since: 2.24
 **/
void
g_variant_unref (GVariant *value)
{
  if (g_atomic_int_dec_and_test (&value->ref_count))
    {
      if G_UNLIKELY (value->state & STATE_LOCKED)
        g_critical ("attempting to free a locked GVariant instance.  "
                    "This should never happen.");

      value->state |= STATE_LOCKED;

      g_variant_type_info_unref (value->type_info);

      if (value->state & STATE_SERIALISED)
        g_buffer_unref (value->contents.serialised.buffer);
      else
        g_variant_release_children (value);

      memset (value, 0, sizeof (GVariant));
      g_slice_free (GVariant, value);
    }
}
Ejemplo n.º 3
0
/**
 * g_time_zone_new:
 * @identifier: (allow-none): a timezone identifier
 *
 * Creates a #GTimeZone corresponding to @identifier.
 *
 * @identifier can either be an RFC3339/ISO 8601 time offset or
 * something that would pass as a valid value for the
 * <varname>TZ</varname> environment variable (including %NULL).
 *
 * Valid RFC3339 time offsets are <literal>"Z"</literal> (for UTC) or
 * <literal>"±hh:mm"</literal>.  ISO 8601 additionally specifies
 * <literal>"±hhmm"</literal> and <literal>"±hh"</literal>.
 *
 * The <varname>TZ</varname> environment variable typically corresponds
 * to the name of a file in the zoneinfo database, but there are many
 * other possibilities.  Note that those other possibilities are not
 * currently implemented, but are planned.
 *
 * g_time_zone_new_local() calls this function with the value of the
 * <varname>TZ</varname> environment variable.  This function itself is
 * independent of the value of <varname>TZ</varname>, but if @identifier
 * is %NULL then <filename>/etc/localtime</filename> will be consulted
 * to discover the correct timezone.
 *
 * See <ulink
 * url='http://tools.ietf.org/html/rfc3339#section-5.6'>RFC3339
 * §5.6</ulink> for a precise definition of valid RFC3339 time offsets
 * (the <varname>time-offset</varname> expansion) and ISO 8601 for the
 * full list of valid time offsets.  See <ulink
 * url='http://www.gnu.org/s/libc/manual/html_node/TZ-Variable.html'>The
 * GNU C Library manual</ulink> for an explanation of the possible
 * values of the <varname>TZ</varname> environment variable.
 *
 * You should release the return value by calling g_time_zone_unref()
 * when you are done with it.
 *
 * Returns: the requested timezone
 *
 * Since: 2.26
 **/
GTimeZone *
g_time_zone_new (const gchar *identifier)
{
  GTimeZone *tz;

  G_LOCK (time_zones);
  if (time_zones == NULL)
    time_zones = g_hash_table_new (g_str_hash0,
                                   g_str_equal0);

  tz = g_hash_table_lookup (time_zones, identifier);
  if (tz == NULL)
    {
      tz = g_slice_new0 (GTimeZone);
      tz->name = g_strdup (identifier);
      tz->ref_count = 0;

      tz->zoneinfo = zone_for_constant_offset (identifier);

      if (tz->zoneinfo == NULL)
        {
          gchar *filename;

          if (identifier != NULL)
            {
              const gchar *tzdir;

              tzdir = getenv ("TZDIR");
              if (tzdir == NULL)
                tzdir = "/usr/share/zoneinfo";

              filename = g_build_filename (tzdir, identifier, NULL);
            }
          else
            filename = g_strdup ("/etc/localtime");

          tz->zoneinfo = (GBuffer *) g_mapped_file_new (filename, FALSE, NULL);
          g_free (filename);
        }

      if (tz->zoneinfo != NULL)
        {
          const struct tzhead *header = tz->zoneinfo->data;
          gsize size = tz->zoneinfo->size;

          /* we only bother to support version 2 */
          if (size < sizeof (struct tzhead) || memcmp (header, "TZif2", 5))
            {
              g_buffer_unref (tz->zoneinfo);
              tz->zoneinfo = NULL;
            }
          else
            {
              gint typecnt;

              /* we trust the file completely. */
              tz->header = (const struct tzhead *)
                (((const gchar *) (header + 1)) +
                  guint32_from_be(header->tzh_ttisgmtcnt) +
                  guint32_from_be(header->tzh_ttisstdcnt) +
                  8 * guint32_from_be(header->tzh_leapcnt) +
                  5 * guint32_from_be(header->tzh_timecnt) +
                  6 * guint32_from_be(header->tzh_typecnt) +
                  guint32_from_be(header->tzh_charcnt));

              typecnt     = guint32_from_be (tz->header->tzh_typecnt);
              tz->timecnt = guint32_from_be (tz->header->tzh_timecnt);
              tz->trans   = (gconstpointer) (tz->header + 1);
              tz->indices = (gconstpointer) (tz->trans + tz->timecnt);
              tz->infos   = (gconstpointer) (tz->indices + tz->timecnt);
              tz->abbrs   = (gconstpointer) (tz->infos + typecnt);
            }
        }

      g_hash_table_insert (time_zones, tz->name, tz);
    }
  g_atomic_int_inc (&tz->ref_count);
  G_UNLOCK (time_zones);

  return tz;
}