#include #include #include #include #include #include #include #include #include "misc.h" char *read_file(const char *filename, long *size) { /* Open the file. */ FILE *fp = fopen(filename, "r"); /* Size of the file, in bytes. */ long filesize = 0; /* Buffer of the file contents. */ char *buf; /* Return NULL, if we couldn't open the file. */ if (fp == NULL) { return NULL; } /* Return NULL, if we couldn't seek to the end of the file. */ if (fseek(fp, 0L, SEEK_END)) { fclose(fp); return NULL; } /* Get the size of the file, in bytes. */ filesize = ftell(fp); /* Return NULL, if the returned size is negative. */ if (filesize < 0) { fclose(fp); return NULL; } /* Allocate enough space for the entire file, plus one. */ buf = calloc(filesize+1, sizeof(char)); /* Return NULL, if the buffer wasn't allocated. */ if (buf == NULL) { fclose(fp); return NULL; } /* Seek back to the start of the file. */ rewind(fp); /* Read the entire file contents into the buffer. */ fread(buf, sizeof(char), filesize, fp); /* Close the file. */ fclose(fp); /* Return the filesize, in bytes. */ *size = filesize; /* Return the buffer. */ return buf; } char *get_line(char **str) { if (str == NULL || is_empty(*str)) { return NULL; } else { size_t i = strcspn(*str, "\n"); char *s = calloc(i+1, sizeof(char)); memcpy(s, *str, i); *str += (i+1); return s; } } static int escape_span(char *str, char *cursor, const char *delm) { if (!is_empty(str) && !is_empty(cursor)) { char *s; if (*str == '\\') { const int span = strspn(str, "\\"); if (&str[span] == cursor) { return span; } } for (s = cursor-1; s > str && *s == '\\'; --s); return (cursor-s)-1; } else { return -1; } } char *find_delm(char *str, const char *delm, int skip_delm) { if (!is_empty(str)) { while (*str != '\0') { char *s = str; str += strcspn(str, delm); if (str[-1] == '\\') { const int span = escape_span(s, str, delm); if (span > 0 && span % 2) { str += strspn(++str, delm); continue; } } break; } return (skip_delm) ? &str[strspn(str, delm)] : str; } else { return NULL; } } char *remove_trailing_whitespace(char *str) { const char *whitespace = " \t\v\r\n"; char *s = str; for (char *tmp = s; !is_empty(tmp); s = tmp, tmp = find_delm(tmp, whitespace, 1)); *find_delm(s, whitespace, 0) = '\0'; return str; } char *get_str_delm_range(char *str, const char *start_delm, const char *end_delm, char **rhs) { if (!is_empty(str)) { char *start = find_delm(str, start_delm, 1); char *end = find_delm(start, end_delm, 0); char *dummy; rhs = (rhs != NULL) ? rhs : &dummy; *end++ = '\0'; *rhs = &end[strspn(end, end_delm)]; return start; } else { return NULL; } } char *make_str(const char *str) { const size_t length = strlen(str); char *s = calloc(length+1, sizeof(char)); memcpy(s, str, length+1); return s; } char *dir_path_num(const char *root, int num) { /* Get the length of the path. */ int len = snprintf(NULL, 0, "%s/%i", root, num); /* Create the directory path. */ char *dir = calloc(len+1, sizeof(char)); sprintf(dir, "%s/%i", root, num); return dir; } char *dir_path_name(const char *root, char *name) { if (!is_empty(root)) { if (!is_empty(name)) { /* Create the directory path. */ char *dir = calloc(format_len("%s/%s", root, name)+1, sizeof(char)); sprintf(dir, "%s/%s", root, name); return dir; } else { return make_str(root); } } else { return NULL; } } int delm_span(char *str, const char delm) { int i; for (i = 0; str[i] == delm; i++); return i; } int sanitize_strlen(char *str) { int len = 0; while (*str != '\0') { const int tok_span = strcspn(str, " ."); const int tok_len = (tok_span) ? tok_span : 1; const char delm = (tok_span) ? str[tok_len] : '\0'; const int span_len = (delm != '\0') ? delm_span(&str[tok_len+1], delm) : 0; str += (tok_len + span_len); len += tok_len; } return len; } char *sanitize_str(char *str) { const int len = sanitize_strlen(str); char *san_str = calloc(len+1, sizeof(char)); char *tmp = san_str; while (*str != '\0' && tmp < &san_str[len]) { const int tok_span = strcspn(str, " ."); const int tok_len = (tok_span) ? tok_span : 1; const char delm = (tok_span) ? str[tok_len] : '\0'; const int span_len = (delm != '\0') ? delm_span(&str[tok_len+1], delm) : 0; memcpy(tmp, str, tok_len); tmp += tok_len; str += (tok_len + span_len); *tmp = (delm == ' ') ? '-' : delm; } return san_str; } char *sanitized_dir_path_name(const char *root, char *name) { char *san_name = sanitize_str(name); char *dir = dir_path_name(root, san_name); free(san_name); return dir; } char *find_alpha(const char *str) { for (; !isalpha(*str); str++); return (char *)str; } char *create_num_str(const char *str, int num) { char *name; int lead_num = strtol(str, &name, 10); const char *sep = (*name != '-') ? "-" : ""; const char *s = find_alpha(name); name = calloc(format_len("%04d%s%s", num, sep, s), sizeof(char)); sprintf(name, "%04d%s%s", num, sep, str); return name; } int is_empty(const char *str) { return (str == NULL) || (*str == '\0'); } char *skip_whitespace(const char *str) { if (is_empty(str)) { return NULL; } else { const size_t span = strspn(str, " \t\v\r\n"); return (char *)&str[span]; } } int vformat_len_copy(const char *fmt, va_list args) { int len; va_list tmp_args; va_copy(tmp_args, args); len = vformat_len(fmt, tmp_args); va_end(tmp_args); return len; } int vformat_len(const char *fmt, va_list args) { return vsnprintf(NULL, 0, fmt, args); } int format_len(const char *fmt, ...) { int len; va_list args; va_start(args, fmt); len = vformat_len(fmt, args); va_end(args); return len; } int is_dir(const char *path) { DIR *dir; if (!access(path, F_OK)) { if ((dir = opendir(path)) != NULL) { closedir(dir); return 1; } else { return 0; } } else { return -1; } } void mkdirp(const char *path, int mode) { char *str = make_str(path); for (char *p = find_delm(str, "/", *str == '/'); !is_empty(p); p = find_delm(p, "/", *p == '/')) { const size_t span = strspn(p, "/"); if (*p == '/') { *p = '\0'; } if (is_dir(str) < 0 && mkdir(str, mode) < 0) { break; } if (*p == '\0') { *p = '/'; if (*find_delm(&p[span], "/", 0) != '\0') { p += span; } } } free(str); }