Index: navit/log.c =================================================================== --- navit/log.c (revisão 5496) +++ navit/log.c (cópia de trabalho) @@ -36,6 +36,7 @@ #include "event.h" #include "callback.h" #include "debug.h" +#include "util.h" #include "log.h" struct log_data { @@ -71,10 +72,21 @@ { time_t t; struct tm *tm; + char *new_fmt_str; t=time(NULL); tm=localtime(&t); - strftime(buffer, 4096, fmt, tm); + // Exchange all '%i' by '%%i' in the passed format string, if found. + new_fmt_str=g_strdup_replace_util(fmt, "%i", "%%i", -1); + // Since strftime does not define the '%i' format string option, + // and so could behave differently across c library implementation, + // it needs to be passed as '%%i' instead, because '%%' is defined, + // so strftime will format it back to '%i' again on the buffer. + strftime(buffer, 4096, new_fmt_str, tm); + // Free the memory space used by the modified format string. + dbg(0,"strftime_localtime: fmt=%s; new_fmt_str=%s; buffer=%s\n", + fmt, new_fmt_str, buffer); + g_free(new_fmt_str); } static void @@ -86,18 +98,19 @@ strftime_localtime(buffer, 4096, this_->filename); this_->filename_ex1=g_strdup(buffer); if ((pos=strstr(this_->filename_ex1,"%i"))) { -#ifdef HAVE_API_ANDROID - pos[1]='d'; -#endif i=0; do { g_free(this_->filename_ex2); - this_->filename_ex2=g_strdup_printf(this_->filename_ex1,i++); + // Convert the sequential integer to string representation, + // reusing the local char buffer to store the result. + g_snprintf(buffer, 4096, "%d", i++); + // Replace all occurrences of '%i' formatting option in filename, + // each by the sequential integer in string representation stored in the buffer. + this_->filename_ex2=g_strdup_replace_util(this_->filename_ex1,"%i", buffer, -1); + dbg(0,"expand_filenames: filename_ex1=%s; filename_ex2=%s\n", + this_->filename_ex1, this_->filename_ex2); } while (file_exists(this_->filename_ex2)); -#ifdef HAVE_API_ANDROID - pos[1]='i'; -#endif - } else + } else this_->filename_ex2=g_strdup(this_->filename_ex1); } @@ -124,7 +137,7 @@ this_->f=fopen(this_->filename_ex2, "w"); if (! this_->f) return; - if (!this_->overwrite) + if (!this_->overwrite) fseek(this_->f, 0, SEEK_END); this_->empty = !ftell(this_->f); log_set_last_flush(this_); @@ -135,7 +148,7 @@ { if (! this_->f) return; - if (this_->trailer.len) + if (this_->trailer.len) fwrite(this_->trailer.data, 1, this_->trailer.len, this_->f); fflush(this_->f); fclose(this_->f); @@ -154,7 +167,7 @@ if (! this_->f) return; if (this_->empty) { - if (this_->header.len) + if (this_->header.len) fwrite(this_->header.data, 1, this_->header.len, this_->f); if (this_->header.len || this_->data.len) this_->empty=0; @@ -170,7 +183,7 @@ pos=ftell(this_->f); if (pos > 0) { fwrite(this_->trailer.data, 1, this_->trailer.len, this_->f); - fseek(this_->f, pos, SEEK_SET); + fseek(this_->f, pos, SEEK_SET); } } if (flags & log_flag_keep_pointer) Index: navit/navit_shipped.xml =================================================================== --- navit/navit_shipped.xml (revisão 5496) +++ navit/navit_shipped.xml (cópia de trabalho) @@ -170,7 +170,7 @@ source="serial:COM4 baud=4800 parity=N data=8 stop=1" > --> - + Index: navit/util.c =================================================================== --- navit/util.c (revisão 5496) +++ navit/util.c (cópia de trabalho) @@ -103,6 +103,96 @@ return ret; } +/** + * Implements a very basic utility function to replace a given substring match + * by another of arbitrary length on the input string. + * + * It's implemented in simple and straightforward way by allocating + * exact memory amount for the result just once, and aggregating the + * strings in it. + * Warning: This function accepts c-style, null terminated strings only. + * It relies mainly on strlen and strstr standard c library functions, + * it also uses glib string utility and memory management functions, + * so any limitation to those functions should apply. + * It also assumes that a char/gchar type will always be equals to a byte, + * and that arithmetic operation on pointers to char type will increment or + * decrement in byte sized quantities. + * + * @param in input_s input string. + * @param in search_s substring to match and to be replaced in the + * input string. If NULL, a copy of input string + * is returned. If it is empty and input string length is + * greater than zero, a copy of input string + * is returned. + * @param in replace_s replacement string. If NULL, a copy of input string + * is returned. If input and search strings are both empty, + * a copy of replace string is returned. + * @param in n_subst number up to substitutions to be made from the + * start of the input string, -1 to replace all. If 0, a copy + * of input string is returned. + * @return new string with replaced occurrences of search by replace + * string, use gfree() to free after use. + */ +gchar * +g_strdup_replace_util(const gchar *input_s, const gchar *search_s, + const gchar *replace_s, gint n_subst) { + gchar *ret; + gint match_count = 0; + const gchar *scan_ptr = input_s, *match_ptr; + glong input_len, unchanged_len, match_len, replace_len, result_len = 0; + gsize alloc_size; + // Validate the inputs in order to prevent unexpected behaviour + if (!input_s || !search_s || !replace_s || !n_subst) + return g_strdup(input_s); + // Handle special cases first. + if ('\0' == *search_s) { + if ('\0' == *input_s) + return g_strdup(replace_s); + else + return g_strdup(input_s); + } + // Get the matching string pattern length. + match_len = strlen(search_s); + // Count the number of substitutions to be made on the input string. + while (((match_count < n_subst) || (-1 >= n_subst)) && + (match_ptr = strstr(scan_ptr, search_s))) { + // Advance the string scanning pointer to the position + // just after the end of matched string segment. + scan_ptr = match_ptr + match_len; + // Count the number of matches done. + ++match_count; + } + // Get the input string length. + input_len = (gsize) (scan_ptr - input_s) + strlen(scan_ptr); + // Get the replacement string length. + replace_len = strlen(replace_s); + // Allocate memory space for result including the terminating null byte. + alloc_size = input_len - match_count * match_len + match_count * replace_len + 1; + //printf("mc=%d, ml=%ld, il=%ld, rl=%ld, alloc=%d, ", match_count, match_len, input_len, replace_len, alloc_size); + ret = g_new(gchar, alloc_size); + // Scan the input string again and compose the resulting string. + for (scan_ptr = input_s; match_count && + (match_ptr = strstr(scan_ptr, search_s)); + scan_ptr = match_ptr + match_len) { + // Get the length of partial string that is left unchanged. + unchanged_len = (gsize) (match_ptr - scan_ptr); + // Copy and append an unchanged string chunk. + g_memmove(ret + result_len, scan_ptr, unchanged_len); + // Update the resulting string length after appending the unchanged string segment. + result_len += unchanged_len; + // Copy and append a replacement instance. + g_memmove(ret + result_len, replace_s, replace_len); + // Update the resulting string length after appending the replacement string. + result_len += replace_len; + // Decrement to update the remaining replacement left. + --match_count; + } + // Copy the remaining chunk including the null byte to complete the resulting string. + g_memmove(ret + result_len, scan_ptr, input_len - (scan_ptr - input_s) + 1); + // Finally, return the resulting new string. + return ret; +} + #ifndef HAVE_GLIB int g_utf8_strlen_force_link(gchar *buffer, int max); int Index: navit/util.h =================================================================== --- navit/util.h (revisão 5496) +++ navit/util.h (cópia de trabalho) @@ -28,6 +28,7 @@ GList * g_hash_to_list(GHashTable *h); GList * g_hash_to_list_keys(GHashTable *h); gchar * g_strconcat_printf(gchar *buffer, gchar *fmt, ...); +gchar * g_strdup_replace_util(const gchar *input_s, const gchar *search_s, const gchar *replace_s, gint n_subst); #if defined(_WIN32) || defined(__CEGCC__) || defined (__APPLE__) || defined(HAVE_API_ANDROID) #if defined(_UNICODE) wchar_t* newSysString(const char *toconvert);