Logo Search packages:      
Sourcecode: uget version File versions  Download package

ug_utils.c

/*
 *
 *   Copyright (C) 2005-2009 by Raymond Huang
 *   plushuang at users.sourceforge.net
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU Lesser General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include <assert.h>
#include <errno.h>
#include <string.h>

#include <gio/gio.h>
#include <ug_class.h>
#include <ug_utils.h>
#include <ug_dataset.h>
#include <ug_data_download.h>
#include <ug_plugin_curl.h>

// ------------------------------------------------------------------
// global functions

gboolean ug_global_init (void)
{
      // data
      ug_data_class_register (UgDataCommonClass);
      ug_data_class_register (UgProgressClass);
      ug_data_class_register (UgDataProxyClass);
      ug_data_class_register (UgDataHttpClass);
      ug_data_class_register (UgDataFtpClass);
      // plug-ins
      ug_plugin_class_register (UgPluginCurlClass);

      return TRUE;
}

void ug_global_finalize (void)
{
      // data
      ug_data_class_unregister (UgDataCommonClass);
      ug_data_class_unregister (UgProgressClass);
      ug_data_class_unregister (UgDataProxyClass);
      ug_data_class_unregister (UgDataHttpClass);
      ug_data_class_unregister (UgDataFtpClass);
      // plug-ins
      ug_plugin_class_unregister (UgPluginCurlClass);
}

// ------------------------------------------------------------------
// string functions

/*  This function works like strcspn ()
 *  If string_len == -1, string is null-terminated.
 *  It return the index of the first character in string that is in charset.
 *  If none of the characters in string is in charset, then the return value is the length of string.
 */
unsigned int ug_str_find_charset (const char* string, int string_len, unsigned int offset, const char* charset)
{
      const char* string_end;
      const char* string_cur;
      const char* ch;

      if (string_len == -1)
            string_len = (int) strlen (string);
      string_end = string + string_len;

      for (string_cur = string + offset;  string_cur < string_end;  string_cur++) {
            for (ch = charset;  *ch;  ch++) {
                  if (*string_cur == *ch)
                        return (unsigned int) (string_cur - string);
            }
      }

      return string_len;
}

/*
 *  This function try to skip specified character from offset in string.
 *  If found other than specified character, return current offset.
 *  Otherwise return original offset.
 */
unsigned int ug_str_skip_charset (const char* string, int string_len, unsigned int offset, const char* charset)
{
      const char* string_cur;
      const char* string_end;
      const char* ch;

      if (string_len == -1)
            string_len = (int) strlen (string);
      string_end = string + string_len;

      for (string_cur = string + offset;  string_cur < string_end;  string_cur++) {
            for (ch = charset;  ;  ch++) {
                  if (*ch == 0)
                        goto exit;
                  if (*string_cur == *ch)
                        break;
            }
      }

exit:
      return (unsigned int) (string_cur - string);
}

/*
 *  This function try to clear specified character from tail of string. (set character to '\0')
 *  return new string_len.
 */
unsigned int ug_str_clear_tail_charset (char* string, int string_len, const char* charset)
{
      const char* ch;
      char*       string_cur;

      if (string_len == -1)
            string_len = (int) strlen (string);

      for (string_cur = string +string_len -1;  string_cur >= string;  string_cur--) {
            for (ch = charset;  ;  ch++) {
                  if (*ch == 0)
                        goto exit;
                  if (*string_cur == *ch) {
                        *string_cur = 0;
                        break;
                  }
            }
      }

exit:
      return (unsigned int) (string_cur - string + 1);
}

/*
 *  count line length until character '\r' , '\n' ,or end of string from offset in string.
 *  return : length of this line.
 */
unsigned int ug_str_line_len (const char* string, int string_len, unsigned int offset)
{
      unsigned int result;

      result = ug_str_find_charset(string, string_len, offset, "\r\n");
      if (result > offset)
            return result - offset;
      return 0;
}

/*
 *  return : offset of next line in string.
 *  return string_len if no next line.
 */
unsigned int ug_str_line_next (const char* string, int string_len, unsigned int offset)
{
      const char* string_end;
      const char* string_cur;

      if (string_len == -1)
            string_len = (int) strlen (string);
      string_end = string + string_len;

      for (string_cur = string + offset;  string_cur < string_end;  string_cur++) {
            if (*string_cur == '\n')
                  return (unsigned int) (string_cur - string) + 1;
      }

      return string_len;
}

/*
 * It free original string that point by string_pointer and copy a new src string to string_pointer.
 * If src_len is -1, src string is null-terminated.
 * If src is NULL, *string_pointer will set NULL.
 *
 *  char* temp_str = strdup ("123");
 *
 *  ug_str_set (&temp_str, "45678", -1);        // temp_str will set "45678"
 */
void  ug_str_set (char** string_pointer, const char* src, int src_len)
{
      g_free (*string_pointer);

      if (src == NULL || *src == 0) {
            *string_pointer = NULL;
            return;
      }

      if (src_len == -1)
            *string_pointer = g_strdup (src);
      else
            *string_pointer = g_strndup (src, src_len);
}

/*
 * convert double to string
 * If number large than 1024, it will append unit string like "KB", "MB", "GB", or "TB" to string.
 */
#define     UNIT_STR_ARRAY_LEN            5
static const gchar* unit_str[UNIT_STR_ARRAY_LEN] = {"", " KB", " MB", " GB", " TB"};

gchar*      ug_str_dtoa_unit (gdouble value, gint precision, const gchar* tail)
{
      guint  index;

      for (index=0; index < UNIT_STR_ARRAY_LEN; index++) {
            if (value < 1024.0)
                  break;
            value /= 1024.0;
      }
      if (index == 0)
            precision = 0;

      return g_strdup_printf ("%.*f%s%s", precision, value, unit_str[index], (tail) ? tail : "");
}

/*
 * convert time to string (hh:mm:ss)
 */
gchar*      ug_str_from_time (guint seconds, gboolean limit_99_99_99)
{
      guint       hour, minute;
      guint       day, year;

      minute  = seconds / 60;
      hour    = minute / 60;
      minute  = minute % 60;
      seconds = seconds % 60;

      if (hour < 100)
            return g_strdup_printf ("%.2u:%.2u:%.2u", hour, minute, seconds);
      else if (limit_99_99_99)
            return g_strdup ("99:99:99");
      else {
            day    = hour / 24;
            year   = day / 365;
            if (year)
                  return g_strdup ("> 1 year");
            else
                  return g_strdup_printf ("%u days", day);
      }
}


// ------------------------------------------------------------------
// file & directory functions

#ifndef _WIN32
int  ug_rename (const gchar *old_filename, const gchar *new_filename)
{
      if (g_get_filename_charsets (NULL))
            return g_rename (old_filename, new_filename);
      else {
            gchar *cp_old_filename = g_filename_from_utf8 (old_filename, -1, NULL, NULL, NULL);
            gchar *cp_new_filename = g_filename_from_utf8 (new_filename, -1, NULL, NULL, NULL);
            int save_errno;
            int retval;

            if (cp_old_filename == NULL || cp_new_filename == NULL) {
                  g_free (cp_old_filename);
                  g_free (cp_new_filename);
                  errno = EINVAL;
                  return -1;
            }

            retval = g_rename (cp_old_filename, cp_new_filename);
            save_errno = errno;

            g_free (cp_old_filename);
            g_free (cp_new_filename);

            errno = save_errno;
            return retval;
      }
}

int  ug_unlink (const gchar *filename)
{
      if (g_get_filename_charsets (NULL))
            return g_unlink (filename);
      else {
            gchar *cp_filename = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
            int save_errno;
            int retval;

            if (cp_filename == NULL) {
                  errno = EINVAL;
                  return -1;
            }

            retval = g_unlink (cp_filename);
            save_errno = errno;

            g_free (cp_filename);

            errno = save_errno;
            return retval;
      }
}

int  ug_create_dir (const gchar *dirname_utf8)
{
      if (g_get_filename_charsets (NULL))
            return g_mkdir (dirname_utf8, 0755);
      else {
            gchar *cp_filename = g_filename_from_utf8 (dirname_utf8, -1, NULL, NULL, NULL);
            int save_errno;
            int retval;

            if (cp_filename == NULL) {
                  errno = EINVAL;
                  return -1;
            }

            retval = g_mkdir (cp_filename, 0755);
            save_errno = errno;

            g_free (cp_filename);

            errno = save_errno;
            return retval;
      }
}

int  ug_delete_dir (const gchar *dirname_utf8)
{
      if (g_get_filename_charsets (NULL))
            return g_rmdir (dirname_utf8);
      else {
            gchar *cp_filename = g_filename_from_utf8 (dirname_utf8, -1, NULL, NULL, NULL);
            int save_errno;
            int retval;

            if (cp_filename == NULL) {
                  errno = EINVAL;
                  return -1;
            }

            retval = g_rmdir (cp_filename);
            save_errno = errno;

            g_free (cp_filename);

            errno = save_errno;
            return retval;
      }
}
#endif


// This function use complex way to handle directory because some locale encoding doesn't avoid '\\' or '/'.
int  ug_create_dir_all (const gchar* dir, gint len)
{
      const gchar*      dir_end;
      const gchar*      element_end;      // path element
      gchar*                  element_os;

      if (len == -1)
            len = strlen (dir);
      dir_end = dir + len;
      element_end = dir;

      for (;;) {
            // skip directory separator "\\\\" or "//"
            for (;  element_end < dir_end;  element_end++) {
                  if (*element_end != G_DIR_SEPARATOR)
                        break;
            }
            if (element_end == dir_end)
                  return 0;
            // get directory name [dir, element_end)
            for (;  element_end < dir_end;  element_end++) {
                  if (*element_end == G_DIR_SEPARATOR)
                        break;
            }
            // create directory by locale encoding name.
            element_os = g_filename_from_utf8 (dir, element_end - dir, NULL, NULL, NULL);
            if (element_os == NULL)
                  break;
            if (g_file_test (element_os, G_FILE_TEST_EXISTS) == FALSE) {
                  if (g_mkdir (element_os, 0755) == -1) {
                        g_free (element_os);
                        break;
                  }
            }
            else if (g_file_test (element_os, G_FILE_TEST_IS_DIR) == FALSE) {
                  g_free (element_os);
                  break;
            }
            g_free (element_os);
      }

      return -1;
}

// launch default application for file.
#ifdef _WIN32
gboolean    ug_launch_default_app (const gchar* folder, const gchar* file)
{
      gchar*            path;
      gunichar2*  path_wcs;

      path = g_build_filename (folder, file, NULL);
      if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) {
            g_free (path);
            return FALSE;
      }

      // UNICODE
      path_wcs = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL);
      g_free (path);
      ShellExecuteW (NULL, L"open", path_wcs, NULL, NULL, SW_SHOW);
      g_free (path_wcs);

      return TRUE;
}
#else
gboolean    ug_launch_default_app (const gchar* folder, const gchar* file)
{
      GError* error = NULL;
      GFile*      gfile;
      gchar*      uri;
      gchar*      path;
      gchar*      path_wcs;

      path = g_build_filename (folder, file, NULL);
      path_wcs = g_filename_from_utf8 (path, -1, NULL, NULL, NULL);
      g_free (path);
      if (g_file_test (path_wcs, G_FILE_TEST_EXISTS) == FALSE) {
            g_free (path_wcs);
            return FALSE;
      }

      gfile = g_file_new_for_path (path_wcs);
      g_free (path_wcs);
      uri = g_file_get_uri (gfile);
      g_object_unref (gfile);
      g_app_info_launch_default_for_uri (uri, NULL, &error);
      g_free (uri);

      if (error) {
#ifndef NDEBUG
            g_print (error->message);
#endif
            g_error_free (error);
      }

      return TRUE;
}
#endif


Generated by  Doxygen 1.6.0   Back to index