#include #include #include #include #include #include "dumbLog.h" #include "util.h" const uint MAX_FILESIZE = 2 * 1024 * 1024; // 2MB const uint MAX_STRING_LENGTH = 1024; //----------------- // C Strings const char* utilBaseName(const char* path_str) { assert(std::strlen(path_str) < MAX_STRING_LENGTH); const char* output = std::strrchr(path_str, '/'); if (output) return output; else return path_str; } bool utilCopyCStr(char* dest, const char* src, uint max_len) { assert(std::strlen(src) < MAX_STRING_LENGTH && max_len <= MAX_STRING_LENGTH); if (std::strlen(src) + 1 > max_len) return false; std::memcpy(dest, src, std::strlen(src) + 1); return true; } char* utilConcatPath(char* out, const char* base_dir, const char* file_name, uint max_len) { size_t l1 = std::strlen(base_dir); size_t l2 = std::strlen(file_name); size_t padded = l1 + l2 + 2; // NOTE: null term + '/' assert(padded <= MAX_STRING_LENGTH && padded <= max_len); int c = std::snprintf(out, padded, "%s/%s", base_dir, file_name); assert(c > 0); return out; } bool utilMatchPrefix(const char* lhs, const char* rhs, int sz) { int rc = strncmp(lhs, rhs, sz); return (rc >= 0); } //----------------- // Memory allocation void * utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int line) { assert(item_count > 0); // that was a fun bug void* mem = std::calloc(item_count, type_size); if (mem == nullptr) { LOG(Error) << "Memory allocation failed, called from " << file_name << ":" << line; } assert(mem != nullptr); // might as well stop execution here return mem; } void utilSafeFree(const void* mem) { if (mem != nullptr) std::free((void *) mem); } //----------------- // File I/O // TODO: don't use ftell() to get filesize // https://wiki.sei.cmu.edu/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file char * utilDumpTextFile(const char* filename) { LOG(Info) << "loading filename, " << filename << "\n"; std::FILE* fp = std::fopen(filename, "rt"); assert(fp); std::fseek(fp, 0, SEEK_END); uint length = std::ftell(fp); std::fseek(fp, 0, SEEK_SET); assert(length < MAX_FILESIZE); // TODO: check error codes for fseek and ftell char* buf = UTIL_ALLOC(length, char); assert(buf); std::fread(buf, sizeof(char), length, fp); // TODO: check fp w/ ferror() here return buf; } // TODO: might want to do the base_dir concat in this function to prevent clobbering // user files on accident bool utilWriteTextFile(const char* filename, const char* text) { size_t text_len = std::strlen(text); if (text_len >= MAX_FILESIZE) { LOG(Error) << "that string is too big\n"; return false; } std::FILE* fp = fopen(filename, "wt"); if (fp) { size_t written = fwrite(text, sizeof(char), text_len, fp); fclose(fp); if (written == text_len) { LOG(Debug) << "successfuly wrote " << written << " bytes\n"; return true; } else { LOG(Error) << "error writing to file: " << filename << "\n"; return false; } } LOG(Debug) << text << "\n"; return false; }