#include "str.h" #include <ctype.h> #include <stdarg.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> char **str_split(char *str, char delim) { char **ret; if (str == NULL) return NULL; if (*str == '\n') { ret = malloc(sizeof(char *)); *ret = NULL; return ret; } int count = 0; char *begin = str; for (char *p = str; *p != '\0'; p++) { if (*p != delim && !(delim == '\0' && isspace(*p))) { continue; } int size = p - begin; if (size > 0) count++; } count++; ret = malloc((count + 1) * sizeof(char *)); memset(ret, 0, (count + 1) * sizeof(char *)); begin = str; int i = 0; bool finished = false; for (char *p = str; !finished; p++) { if (*p == '\0') finished = true; if (*p != delim && *p != '\0' && !(delim == '\0' && isspace(*p))) { continue; } int size = p - begin; if (size == 0) { begin = p + 1; continue; } char *buf = malloc(sizeof(char) * (size + 1)); buf[size] = '\0'; memcpy(buf, begin, size * sizeof(char)); begin = p + 1; ret[i] = buf; i++; } return ret; } void destroy_str_list(char **list) { char **p = list; while (*p != NULL) { free(*p); p++; } free(list); } char *str_strip(char *str) { if (str == NULL) return NULL; int len = strlen(str); char *begin = str; char *end = str + len - 1; while (isspace(*begin) && begin < end) { begin++; } while (isspace(*end) && end >= begin) { end--; } len = end - begin + 1; char *buf = malloc(sizeof(char) * (len) + 1); buf[len] = '\0'; memcpy(buf, begin, len); return buf; } void init_str_builder(str_builder_t *sb) { *sb = (str_builder_t){.size = 0, .cap = 16}; sb->buf = malloc(sizeof(char) * 17); } static void sb_reserve(str_builder_t *sb, int extra) { if (sb->size + extra <= sb->cap) { return; } int new_cap = (sb->size + extra) * 2; sb->buf = realloc(sb->buf, new_cap + 1); memset(sb->buf + sb->cap, 0, new_cap - sb->cap + 1); sb->cap = new_cap; } void str_builder_append(str_builder_t *sb, char *format, ...) { va_list va1; va_list va2; va_start(va1, format); va_copy(va2, va1); int size = vsnprintf(NULL, 0, format, va1); sb_reserve(sb, size); vsnprintf(sb->buf + sb->size, sb->cap - sb->size + 1, format, va2); } void str_builder_append_char(str_builder_t *sb, char c) { sb_reserve(sb, 1); sb->buf[sb->size] = c; sb->size++; } char *fgetline(FILE *fp) { str_builder_t sb; init_str_builder(&sb); while (true) { int c = fgetc(fp); if (c == EOF && sb.size == 0) return NULL; if (c != EOF) str_builder_append_char(&sb, c); if (c == EOF || c == '\n') return sb.buf; } return NULL; } int fpeek(FILE *fp) { int c = fgetc(fp); if (c == EOF) return c; ungetc(c, fp); return c; }