/* Jungle Monkey * Copyright (C) 1999, 2000 The Regents of the University of Michigan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _UTIL_H #define _UTIL_H #include #include #include #include #include #include #ifndef G_MAXUINT #define G_MAXUINT UINT_MAX #endif #ifndef G_MAXUINT16 #define G_MAXUINT16 65535 #endif #ifndef G_MAXUINT32 #define G_MAXUINT32 4294967295U #endif /* ******************************************** */ /* General functions/macros */ /** Round n up to the nearest base. */ #define ROUNDUP(n, base) ( (((n) % (base)) == 0) ? \ (n) :\ ((n) + ((base) - ((n) % (base)))) ) /* ******************************************** */ /* Timeval related macros and functions. */ typedef struct timeval Timeval; /* Convert a double to a timeval */ #define double2timer(dubl, tvp) \ do { \ (tvp)->tv_sec = (int) floor(dubl); \ (tvp)->tv_usec = (int) ((dubl - floor(dubl)) * 1000000.0); \ while ((tvp)->tv_usec < 0) \ { \ (tvp)->tv_sec -= 1; \ (tvp)->tv_usec += 1000000; \ } \ (tvp)->tv_sec += (tvp)->tv_usec / 1000000; \ (tvp)->tv_usec %= 1000000; \ } while (0) /* Convert a timeval to a double */ #define timer2double(tvp) \ (((double) (tvp)->tv_sec) + (((double) ((tvp)->tv_usec)) / 1000000.0)) #define timernormalize(tvp) \ do { \ while ((tvp)->tv_usec < 0) \ { \ (tvp)->tv_sec -= 1; \ (tvp)->tv_usec += 1000000; \ } \ (tvp)->tv_sec += (tvp)->tv_usec / 1000000; \ (tvp)->tv_usec %= 1000000; \ } while (0) /* Compare less-than two timevals */ #define timerlt(a, b) ( ((a)->tv_sec < (b)->tv_sec) || \ ((a)->tv_sec == (b)->tv_sec && \ (a)->tv_usec < (b)->tv_usec) ) /* Compare less-than-or-equal two timevals */ #define timerleq(a, b) ( ((a)->tv_sec < (b)->tv_sec) || \ ((a)->tv_sec == (b)->tv_sec && \ (a)->tv_usec <= (b)->tv_usec) ) /* if negative, round up to zero */ #define timermakepos(tvp) (((tvp)->tv_sec < 0)) \ ?((tvp)->tv_sec = 0, (tvp)->tv_usec = 0) \ :(0) /* Take absolute value of a timeval */ #define timerabs(a, result) \ do { \ if ((a)->tv_sec < 0) \ { \ (result)->tv_sec = -((a)->tv_sec + 1); \ (result)->tv_usec = 1000000 - (a)->tv_usec; \ } \ else \ { \ *(result) = *(a); \ } \ } while (0) /* Add one timer to another. This is already on most BSD systems */ #ifndef timeradd #define timeradd(a, b, result) \ do { \ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ if ((result)->tv_usec >= 1000000) \ { \ ++(result)->tv_sec; \ (result)->tv_usec -= 1000000; \ } \ } while (0) #endif /* Subtract one timer from another. This is already on most BSD systems */ #ifndef timersub #define timersub(a, b, result) \ do { \ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ if ((result)->tv_usec < 0) { \ --(result)->tv_sec; \ (result)->tv_usec += 1000000; \ } \ } while (0) #endif #define timerusec(tvp) (((tvp)->tv_sec * 1000000) + (tvp)->tv_usec) #define timeraddusec(tvp, usec) \ do { \ (tvp)->tv_sec += usec / 1000000; \ (tvp)->tv_usec += usec % 1000000; \ if ((tvp)->tv_usec < 0) \ { \ (tvp)->tv_sec -= (-((tvp)->tv_usec / 1000000) + 1); \ (tvp)->tv_usec = (1000000 + ((tvp)->tv_usec % 1000000)); \ } \ timernormalize(tvp); \ } while (0) #define timeraddmsec(tvp, msec) \ do { \ (tvp)->tv_sec += msec / 1000; \ (tvp)->tv_usec += msec % 1000; \ if ((tvp)->tv_usec < 0) \ { \ (tvp)->tv_sec -= (-((tvp)->tv_usec / 1000000) + 1); \ (tvp)->tv_usec = (1000000 + ((tvp)->tv_usec % 1000000)); \ } \ timernormalize(tvp); \ } while (0) #define Gettimeofday(T) do { g_assert(gettimeofday(T, NULL) == 0); } while(0) /** Get the time in GMT. */ time_t get_time_gmt(void); /* Get the time in milliseconds. This is like ((time() * 1000) % UINT_MAX), but we use gettimeofday, so it's more accurate. */ unsigned int millitime (void); /* ****************************** */ /* Timers with random delay util functions (so timeout at time + rand() % delay) */ void rand_timer_set (guint* timer, guint time, guint delay, GSourceFunc func, gpointer user_data); void rand_timer_cancel (guint* timer); void rand_timer_reset (guint* timer, guint time, guint delay, GSourceFunc func, gpointer user_data); /* ******************************************** */ /* String functions */ #define SAFESTRCMP(A,B) (((A) && (B))?strcmp((A),(B)):1) char* strcasestr (const char* haystack, const char* needle); /** Thread safe string tokenizer with double quote's. It works like strtok_r. Arguments are string to tokenize, the delimiters, and the next pointer. If you want double quotes, put a double quote in the delim's. It doesn't count \"'s as quotes. TODO: Add single quote's? */ char* strtokq (char* s, const char* delim, char** next); char* stresc (const char* s, const char* esc, char escc); char* strunesc (const char* s, const char* esc, char escc); /** Add quotes around the string s. */ #define strquote(s) (g_strconcat("\"", (s), "\"", NULL)) /** Convert special characters to escape sequences. This includes converting &'s to &'s. */ char* strescape (const char* s); /** Convert escape sequences to special characters. This includes converting &'s to &'s. */ char* strunescape (const char* s); /** Count the number of occurences of any of the characters in chars in s. */ int strchrcount (const char* s, const char* chars); /** Do a strncmp on the suffixes of the strings. */ int strsuffixcmp (const char* s1, const char* s2); /** Convert the string to a readable string. Unreadable characters get converted to \x00 sequences. */ char* strtoreadable (const char* s); /** Get length of string s. len is the maximum length. */ size_t strnlen (const char* s, size_t len); /* ******************************************** */ /* File/program execution functions */ /** Get the size of a file. Returns negative number if there was an error. */ int file_size (const char* path); int FILE_size (FILE* file); char* filesize_to_string (int size); char* filesize_fraction_to_string (int offset, int size); /** Check if the file exists and is readable. */ int file_exists (const char* path); char* tilde_expand (const char* path); /** Check if the path is a directory. Returns TRUE if the path is a directory, FALSE otherwise. */ int is_file (const char* path); int is_dir (const char* path); /** Make the directory recursively. Returns TRUE on success. This attempts to create the path given, if this cannot be done, it attempts to mkdir the parent directory and so on. When this is done, it tries again. */ int mkdirr (const gchar* path, gint mode); /** Check if the name is just an ok file name. An ok file name is any name that isn't just whitespace, isn't '.' or '..', and doesn't have '/' in it. Anything else is allowed. */ int is_okfilename (const char* name); /** Check if the path is an ok path name. A good path is made of up ok file names. This just strtoks the path on '/' and checks to see if each token is an ok file name. */ int is_okpathname (const char* path); /** Check if the name a good file name. A good file name is alphanumeric characters with some punctuation in the middle. A bad file name has weird punctuation in it. We don't allow files that begin with a '.'. Punctuation we allow: period, dash, underscore, space, exclamation point, single quote, double quote, parenthesis, comma, and ampersand. Note if you exec something, you may want to check for ampersand. */ int is_goodfilename (const char* name); /** Check if the path is a good path name. A good path is made of up good file names. This just strtoks the path on '/' and checks to see if each token is a good file name. */ int is_goodpathname (const char* path); /** Log error as critical and then call exit(FAIL). Glib logs as error then calls abort, which dumps core. */ void my_error (const gchar* format, ...); gboolean remove_by_value_hrfunc (gpointer key, gpointer value, gpointer user_data); #endif /* _UTIL_H */