#include <ctype.h>
#include <dirent.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include "misc.h"
char *read_file(const char *filename, long *size) {
FILE *fp = fopen(filename, "r");
long filesize = 0;
char *buf;
if (fp == NULL) {
return NULL;
}
if (fseek(fp, 0L, SEEK_END)) {
fclose(fp);
return NULL;
}
filesize = ftell(fp);
if (filesize < 0) {
fclose(fp);
return NULL;
}
buf = calloc(filesize+1, sizeof(char));
if (buf == NULL) {
fclose(fp);
return NULL;
}
rewind(fp);
fread(buf, sizeof(char), filesize, fp);
fclose(fp);
*size = filesize;
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;
}
}
char *find_delm(char *str, const char *delm, int skip_delm) {
if (!is_empty(str)) {
char *s;
for (s = &str[strcspn(str, delm)]; *s != '\0'; s += strcspn(s, delm)) {
if (*s == '\\') {
s += strspn(++s, delm);
continue;
} else {
break;
}
}
return (skip_delm) ? &s[strspn(s, delm)] : s;
} 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) {
int len = snprintf(NULL, 0, "%s/%i", root, num);
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)) {
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);
}