X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=share%2Fcommon.c;h=38182021dac924d4474af15566ddfaa689609f8b;hb=226cf7f5acab52813e8f2bd30ef09191125041e1;hp=46ec4b008e86fc328edc78a059573ab9427154d4;hpb=b887b51a894fa021d524d9a1b1d66987caf3efd3;p=neverball diff --git a/share/common.c b/share/common.c index 46ec4b0..3818202 100644 --- a/share/common.c +++ b/share/common.c @@ -20,89 +20,123 @@ #include #include #include -#include #include +#include +#include +#include #include "common.h" +#include "fs.h" #define MAXSTR 256 /*---------------------------------------------------------------------------*/ -int read_line(char **dst, FILE *fin) +int read_line(char **dst, fs_file fin) { - char buffer[MAXSTR] = ""; - int buffer_size = 0; + char buff[MAXSTR]; - char *store = NULL; - char *store_new = NULL; - int store_size = 0; + char *line, *new; + size_t len0, len1; - int seen_newline = 0; + line = NULL; - while (!seen_newline) + while (fs_gets(buff, sizeof (buff), fin)) { - if (fgets(buffer, sizeof (buffer), fin) == NULL) + /* Append to data read so far. */ + + if (line) { - if (store_size > 0) - break; - else - { - *dst = NULL; - return 0; - } + new = concat_string(line, buff, NULL); + free(line); + line = new; + } + else + { + line = strdup(buff); } - buffer_size = strlen(buffer) + 1; + /* Strip newline, if any. */ - /* Erase trailing newline. */ + len0 = strlen(line); + strip_newline(line); + len1 = strlen(line); - if (buffer[buffer_size - 2] == '\n') + if (len1 != len0) { - seen_newline = 1; - buffer[buffer_size - 2] = '\0'; - buffer_size--; + /* We hit a newline, clean up and break. */ + line = realloc(line, len1 + 1); + break; } + } - /* Allocate or reallocate space for the buffer. */ + return (*dst = line) ? 1 : 0; +} - if ((store_new = (char *) realloc(store, store_size + buffer_size))) - { - /* Avoid passing garbage to string functions. */ +char *strip_newline(char *str) +{ + char *c = str + strlen(str) - 1; - if (store == NULL) - store_new[0] = '\0'; + while (c >= str && (*c == '\n' || *c =='\r')) + *c-- = '\0'; - store = store_new; - store_size += buffer_size; + return str; +} - store_new = NULL; - } - else +char *dupe_string(const char *src) +{ + char *dst = NULL; + + if (src && (dst = malloc(strlen(src) + 1))) + strcpy(dst, src); + + return dst; +} + +char *concat_string(const char *first, ...) +{ + char *full; + + if ((full = strdup(first))) + { + const char *part; + va_list ap; + + va_start(ap, first); + + while ((part = va_arg(ap, const char *))) { - fprintf(stderr, "Failed to allocate memory.\n"); + char *new; - free(store); - *dst = NULL; - return 0; + if ((new = realloc(full, strlen(full) + strlen(part) + 1))) + { + full = new; + strcat(full, part); + } + else + { + free(full); + full = NULL; + break; + } } - strncat(store, buffer, buffer_size); + va_end(ap); } - *dst = store; - - return 1; + return full; } -char *strip_newline(char *str) +char *trunc_string(const char *src, char *dst, int len) { - char *c = str + strlen(str) - 1; + static const char ell[] = "..."; - while (c >= str && (*c == '\n' || *c =='\r')) - *c-- = '\0'; + assert(len > sizeof (ell)); - return str; + if (dst[len - 1] = '\0', strncpy(dst, src, len), dst[len - 1] != '\0') + strcpy(dst + len - sizeof (ell), ell); + + return dst; } time_t make_time_from_utc(struct tm *tm) @@ -162,31 +196,66 @@ void file_copy(FILE *fin, FILE *fout) fwrite(buff, 1, size, fout); } -char *base_name(const char *name, const char *suffix) +/*---------------------------------------------------------------------------*/ + +int path_is_sep(int c) { - static char buf[MAXSTR]; - char *base; +#ifdef _WIN32 + return c == '/' || c == '\\'; +#else + return c == '/'; +#endif +} - if (!name) - return NULL; +int path_is_abs(const char *path) +{ + if (path_is_sep(path[0])) + return 1; - /* Remove the directory part. */ +#ifdef _WIN32 + if (isalpha(path[0]) && path[1] == ':' && path_is_sep(path[2])) + return 1; +#endif - base = strrchr(name, '/'); + return 0; +} + +static char *path_last_sep(const char *path) +{ + char *sep; + + sep = strrchr(path, '/'); #ifdef _WIN32 - if (!base) - base = strrchr(name, '\\'); + if (!sep) + { + sep = strrchr(path, '\\'); + } else { char *tmp; - if ((tmp = strrchr(base, '\\'))) - base = tmp; + if ((tmp = strrchr(sep, '\\'))) + sep = tmp; } #endif - strncpy(buf, base ? base + 1 : name, sizeof (buf)); + return sep; +} + +char *base_name(const char *name, const char *suffix) +{ + static char buf[MAXSTR]; + char *base; + + if (!name) + return NULL; + + /* Remove the directory part. */ + + base = path_last_sep(name); + + strncpy(buf, base ? base + 1 : name, sizeof (buf) - 1); /* Remove the suffix. */ @@ -201,4 +270,54 @@ char *base_name(const char *name, const char *suffix) return buf; } +const char *dir_name(const char *name) +{ + static char buff[MAXSTR]; + + char *sep; + + strncpy(buff, name, sizeof (buff) - 1); + + if ((sep = path_last_sep(buff))) + { + if (sep == buff) + return "/"; + + *sep = '\0'; + + return buff; + } + + return "."; +} + +/* + * Given a path to a file REF and another path REL relative to REF, + * construct and return a new path that can be used to refer to REL + * directly. + */ +char *path_resolve(const char *ref, const char *rel) +{ + static char new[MAXSTR * 2]; + + if (path_is_abs(rel)) + { + strncpy(new, rel, sizeof (new) - 1); + return new; + } + + strncpy(new, dir_name(ref), sizeof (new) - 1); + strncat(new, "/", sizeof (new) - strlen(new) - 1); + strncat(new, rel, sizeof (new) - strlen(new) - 1); + + return new; +} + +/*---------------------------------------------------------------------------*/ + +int rand_between(int low, int high) +{ + return low + rand() / (RAND_MAX / (high - low + 1) + 1); +} + /*---------------------------------------------------------------------------*/