Blame src/grl-util.c

Packit 67b98c
/*
Packit 67b98c
 * Copyright (C) 2010, 2011 Igalia S.L.
Packit 67b98c
 *
Packit 67b98c
 * Contact: Iago Toral Quiroga <itoral@igalia.com>
Packit 67b98c
 *
Packit 67b98c
 * This library is free software; you can redistribute it and/or
Packit 67b98c
 * modify it under the terms of the GNU Lesser General Public License
Packit 67b98c
 * as published by the Free Software Foundation; version 2.1 of
Packit 67b98c
 * the License, or (at your option) any later version.
Packit 67b98c
 *
Packit 67b98c
 * This library is distributed in the hope that it will be useful, but
Packit 67b98c
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67b98c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit 67b98c
 * Lesser General Public License for more details.
Packit 67b98c
 *
Packit 67b98c
 * You should have received a copy of the GNU Lesser General Public
Packit 67b98c
 * License along with this library; if not, write to the Free Software
Packit 67b98c
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
Packit 67b98c
 * 02110-1301 USA
Packit 67b98c
 *
Packit 67b98c
 */
Packit 67b98c
Packit 67b98c
/**
Packit 67b98c
 * SECTION:grl-util
Packit 67b98c
 * @short_description: utility functions
Packit 67b98c
 */
Packit 67b98c
Packit 67b98c
#include "grl-util.h"
Packit 67b98c
Packit 67b98c
#include <string.h>
Packit 67b98c
Packit 67b98c
/**
Packit 67b98c
 * grl_paging_translate:
Packit 67b98c
 * @skip: number of elements to skip
Packit 67b98c
 * @count: number of elements to retrieve
Packit 67b98c
 * @max_page_size: maximum value for page size (0 for unlimited size)
Packit 67b98c
 * @page_size: optimal page size
Packit 67b98c
 * @page_number: page which contain the first element to retrieve (starting at 1)
Packit 67b98c
 * @internal_offset: in the @page_number, offset where first element can be found (starting at 0)
Packit 67b98c
 *
Packit 67b98c
 * Grilo browsing implements a paging mechanism through @skip and @count values.
Packit 67b98c
 *
Packit 67b98c
 * But there are some services (like Jamendo or Flickr) where paging is done
Packit 67b98c
 * through a page number and page size: user request all elements in a page,
Packit 67b98c
 * specifying in most cases what is the page size.
Packit 67b98c
 *
Packit 67b98c
 * This function is a helper for this task, computing from @skip and @count what
Packit 67b98c
 * is the optimal value of page size (limited by @max_page_size), which page
Packit 67b98c
 * should the user request, and where requested data start inside the page.
Packit 67b98c
 *
Packit 67b98c
 * By optimal we mean that it computes those values so only one page is required
Packit 67b98c
 * to satisfy the data, using the smallest page size. If user is limiting page
Packit 67b98c
 * size, then more requests to services might be needed. But still page size
Packit 67b98c
 * will be an optimal value.
Packit 67b98c
 *
Packit 67b98c
 * If @page_size is @NULL, then page size will be @max_page_size. If the later
Packit 67b98c
 * is also 0, then page size will be #G_MAXUINT.
Packit 67b98c
 *
Packit 67b98c
 * Since: 0.1.6
Packit 67b98c
 **/
Packit 67b98c
void grl_paging_translate (guint skip,
Packit 67b98c
                           guint count,
Packit 67b98c
                           guint max_page_size,
Packit 67b98c
                           guint *page_size,
Packit 67b98c
                           guint *page_number,
Packit 67b98c
                           guint *internal_offset)
Packit 67b98c
{
Packit 67b98c
  gulong _page_size;
Packit 67b98c
  gulong last_element;
Packit 67b98c
Packit 67b98c
  if (!page_size) {
Packit 67b98c
    if (max_page_size > 0) {
Packit 67b98c
      _page_size = max_page_size;
Packit 67b98c
    } else {
Packit 67b98c
      _page_size = G_MAXUINT;
Packit 67b98c
    }
Packit 67b98c
  } else {
Packit 67b98c
    if (skip < count) {
Packit 67b98c
      _page_size = skip + count;
Packit 67b98c
      if (max_page_size > 0) {
Packit 67b98c
        _page_size = CLAMP (_page_size, 0, max_page_size);
Packit 67b98c
      }
Packit 67b98c
    } else {
Packit 67b98c
      _page_size = count;
Packit 67b98c
      last_element = skip + count - 1;
Packit 67b98c
      while (skip/_page_size != last_element/_page_size &&
Packit 67b98c
             (max_page_size == 0 || _page_size < max_page_size)) {
Packit 67b98c
        _page_size++;
Packit 67b98c
      }
Packit 67b98c
    }
Packit 67b98c
    _page_size = CLAMP (_page_size, 0, G_MAXUINT);
Packit 67b98c
  }
Packit 67b98c
Packit 67b98c
  if (page_size) {
Packit 67b98c
    *page_size = _page_size;
Packit 67b98c
  }
Packit 67b98c
Packit 67b98c
  if (page_number) {
Packit 67b98c
    *page_number = skip/_page_size + 1;
Packit 67b98c
  }
Packit 67b98c
Packit 67b98c
  if (internal_offset) {
Packit 67b98c
    *internal_offset = skip%_page_size;
Packit 67b98c
  }
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
/**
Packit 67b98c
 * grl_list_from_va: (skip)
Packit 67b98c
 * @p: first pointer
Packit 67b98c
 * @...: va_list pointers
Packit 67b98c
 *
Packit 67b98c
 * Returns a #GList containing the va_list pointers. Use @NULL to finalize them,
Packit 67b98c
 *
Packit 67b98c
 * Returns: a #GList.
Packit 67b98c
 *
Packit 67b98c
 * Since: 0.1.6
Packit 67b98c
 **/
Packit 67b98c
GList *
Packit 67b98c
grl_list_from_va (gpointer p, ...)
Packit 67b98c
{
Packit 67b98c
  GList *pointer_list = NULL;
Packit 67b98c
  gpointer next_pointer;
Packit 67b98c
  va_list va_pointers;
Packit 67b98c
Packit 67b98c
  va_start (va_pointers, p);
Packit 67b98c
  next_pointer = p;
Packit 67b98c
  while (next_pointer) {
Packit 67b98c
    pointer_list = g_list_prepend (pointer_list, next_pointer);
Packit 67b98c
    next_pointer = va_arg (va_pointers, gpointer);
Packit 67b98c
  }
Packit 67b98c
  va_end (va_pointers);
Packit 67b98c
Packit 67b98c
  return g_list_reverse (pointer_list);
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
/**
Packit 67b98c
 * grl_date_time_from_iso8601:
Packit 67b98c
 * @date: a date expressed in iso8601 format
Packit 67b98c
 *
Packit 67b98c
 * Returns: a newly-allocated #GDateTime set to the time corresponding to
Packit 67b98c
 * @date, or %NULL if @date could not be parsed properly.
Packit 67b98c
 *
Packit 67b98c
 * Since: 0.2.0
Packit 67b98c
 */
Packit 67b98c
GDateTime *
Packit 67b98c
grl_date_time_from_iso8601 (const gchar *date)
Packit 67b98c
{
Packit 67b98c
  GTimeVal t = { 0, };
Packit 67b98c
  gboolean ret;
Packit 67b98c
  gchar *date_time;
Packit 67b98c
  gint date_length;
Packit 67b98c
Packit 67b98c
  if (!date) {
Packit 67b98c
    return NULL;
Packit 67b98c
  }
Packit 67b98c
Packit 67b98c
  ret = g_time_val_from_iso8601 (date, &t);
Packit 67b98c
Packit 67b98c
  /* second condition works around
Packit 67b98c
   * https://bugzilla.gnome.org/show_bug.cgi?id=650968 */
Packit 67b98c
  if (!ret || (t.tv_sec == 0 && t.tv_usec == 0)) {
Packit 67b98c
    /* We might be in the case where there is a date alone. In that case, we
Packit 67b98c
     * take the convention of setting it to noon GMT */
Packit 67b98c
Packit 67b98c
    /* Date can could be YYYY, YYYY-MM, YYYY-MM-DD or YYYYMMDD */
Packit 67b98c
    date_length = strlen (date);
Packit 67b98c
    switch (date_length) {
Packit 67b98c
    case 4:
Packit 67b98c
      date_time = g_strdup_printf ("%s-01-01T12:00:00Z", date);
Packit 67b98c
      break;
Packit 67b98c
    case 7:
Packit 67b98c
      date_time = g_strdup_printf ("%s-01T12:00:00Z", date);
Packit 67b98c
      break;
Packit 67b98c
    default:
Packit 67b98c
      date_time = g_strdup_printf ("%sT12:00:00Z", date);
Packit 67b98c
    }
Packit 67b98c
    ret = g_time_val_from_iso8601 (date_time, &t);
Packit 67b98c
    g_free (date_time);
Packit 67b98c
  }
Packit 67b98c
Packit 67b98c
  if (ret)
Packit 67b98c
    return g_date_time_new_from_timeval_utc (&t);
Packit 67b98c
Packit 67b98c
  return NULL;
Packit 67b98c
}
Packit 67b98c