From a8705ecb0f5d90f81c6bed87f997392b96665c0c Mon Sep 17 00:00:00 2001 From: lifegpc Date: Fri, 7 Jan 2022 21:14:56 +0800 Subject: [PATCH] Update --- CMakeLists.txt | 2 + cfileop.cpp | 26 ++++++++++ cfileop.h | 37 ++++++++++++++ cstr_util.c | 69 +++++++++++++++++++++++++ cstr_util.h | 43 ++++++++++++++++ file_reader.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++ file_reader.h | 58 +++++++++++++++++++++ 7 files changed, 371 insertions(+) create mode 100644 file_reader.c create mode 100644 file_reader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dcf9a10..fe3a06a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ set(SOURCE_FILE encoding.cpp str_util.cpp c_linked_list.cpp + file_reader.c ) set(SOURCE_FILE_HEADERS cfileop.h @@ -68,6 +69,7 @@ set(SOURCE_FILE_HEADERS str_util.h linked_list.h c_linked_list.h + file_reader.h ) add_library(utils STATIC ${SOURCE_FILE} ${SOURCE_FILE_HEADERS}) diff --git a/cfileop.cpp b/cfileop.cpp index c8becfb..a1d9741 100644 --- a/cfileop.cpp +++ b/cfileop.cpp @@ -79,3 +79,29 @@ int fileop_set_file_time(const char* path, time_t ctime, time_t actime, time_t m if (!path) return 0; return fileop::set_file_time(path, ctime, actime, modtime) ? 1 : 0; } + +int fileop_mkdirs(const char* path, int mode, int allow_exists) { + if (!path) return 0; + return fileop::mkdirs(path, mode, allow_exists) ? 1 : 0; +} + +int fileop_get_file_size(const char* path, size_t* size) { + if (!path || !size) return 0; + size_t s; + auto re = fileop::get_file_size(path, s); + if (re) *size = s; + return re ? 1 : 0; +} + +int fileop_fseek(FILE* f, int64_t offset, int origin) { + return fileop::fseek(f, offset, origin); +} + +int fileop_mkdir_for_file(const char* path, int mode) { + if (!path) return 0; + return fileop::mkdir_for_file(path, mode) ? 1 : 0; +} + +int64_t fileop_ftell(FILE* f) { + return fileop::ftell(f); +} diff --git a/cfileop.h b/cfileop.h index 0bebdd9..b000d81 100644 --- a/cfileop.h +++ b/cfileop.h @@ -5,6 +5,7 @@ extern "C" { #endif #include #include +#include #include #include #include @@ -104,6 +105,42 @@ int fileop_set_file_time(const char* path, time_t ctime, time_t actime, time_t m #define fileop_close(fd) (!close(fd)) #endif #define fileop_fclose(stream) (!fclose(stream)) +/** + * @brief Creates a new directory recursively. + * @param path Path for a new directory. + * @param mode Directory permission. (Linux only) + * @param allow_exists If directory is already exists return 1 rather than 0. + * @return 1 if create successfully otherwise 0 +*/ +int fileop_mkdirs(const char* path, int mode, int allow_exists); +/** + * @brief Retrieves the size of the specified file, in bytes. + * @param path The path of file. + * @param size Result. + * @return 1 if successed otherwise 0 +*/ +int fileop_get_file_size(const char* path, size_t* size); +/** + * @brief Moves the file pointer to a specified location. + * @param f File + * @param offset Number of bytes from origin. + * @param origin Initial position. + * @return 0 if successed otherwise a nonzero value +*/ +int fileop_fseek(FILE* f, int64_t offset, int origin); +/** + * @brief Make sure file's directory is already exists, if not exists, try create it. + * @param path File's path + * @param mode Directory permission. (Linux only) + * @return 1 if file's directory is exists now otherwise 0. +*/ +int fileop_mkdir_for_file(const char* path, int mode); +/** + * @brief Gets the current position of a file pointer. + * @param f Target FILE structure. + * @return The current position +*/ +int64_t fileop_ftell(FILE* f); #ifdef __cplusplus } #endif diff --git a/cstr_util.c b/cstr_util.c index 3fc6edb..e64cd2b 100644 --- a/cstr_util.c +++ b/cstr_util.c @@ -1,9 +1,15 @@ #include "cstr_util.h" +#include "utils_config.h" #include +#include #include #include +#if HAVE_PRINTF_S +#define printf printf_s +#endif + int cstr_util_copy_str(char** dest, const char* str) { if (!dest || !str) return 1; size_t le = strlen(str); @@ -52,3 +58,66 @@ int32_t cstr_read_int32(const uint8_t* bytes, int big) { if (!bytes) return 0; return cstr_read_uint32(bytes, big); } + +void cstr_tolowercase2(char* str, size_t len) { + if (!str) return; + if (!len) len = strlen(str); + for (size_t i = 0; i < len; i++) { + str[i] = tolower(str[i]); + } +} + +uint64_t cstr_read_uint64(const uint8_t* bytes, int big) { + if (!bytes) return 0; + return big ? ((uint64_t)bytes[0] << 56) + ((uint64_t)bytes[1] << 48) + ((uint64_t)bytes[2] << 40) + ((uint64_t)bytes[3] << 32) + ((uint64_t)bytes[4] << 24) + ((uint64_t)bytes[5] << 16) + ((uint64_t)bytes[6] << 8) + (uint64_t)bytes[7] : (uint64_t)bytes[0] + ((uint64_t)bytes[1] << 8) + ((uint64_t)bytes[2] << 16) + ((uint64_t)bytes[3] << 24) + ((uint64_t)bytes[4] << 32) + ((uint64_t)bytes[5] << 40) + ((uint64_t)bytes[6] << 48) + ((uint64_t)bytes[7] << 56); +} + +int64_t cstr_read_int64(const uint8_t* bytes, int big) { + if (!bytes) return 0; + return cstr_read_uint64(bytes, big); +} + +uint16_t cstr_read_uint16(const uint8_t* bytes, int big) { + if (!bytes) return 0; + return big ? (bytes[0] << 8) + bytes[1] : bytes[0] + (bytes[1] << 8); +} + +int16_t cstr_read_int16(const uint8_t* bytes, int big) { + if (!bytes) return 0; + return cstr_read_uint16(bytes, big); +} + +int cstr_read_str(char* buf, char** dest, size_t* pos, size_t buf_len) { + if (!buf || !dest || !pos) return 1; + if (*pos >= buf_len) return 1; + char* tmp = NULL; + size_t p = *pos, tmp_len = 128, n = 0; + tmp = malloc(tmp_len); + if (!tmp) { + printf("Out of memory.\n"); + return 1; + } + while (p < buf_len) { + tmp[n] = buf[p]; + if (!buf[p]) break; + p++; + n++; + if (n >= tmp_len) { + tmp_len += 128; + char* ntmp = realloc(tmp, tmp_len); + if (!ntmp) { + printf("Out of memory.\n"); + free(tmp); + return 1; + } + tmp = ntmp; + } + } + if (p == buf_len && tmp[n - 1]) { + tmp[n] = 0; + } + *pos = p >= buf_len ? p : p + 1; + char* ntmp = realloc(tmp, n); + *dest = ntmp ? ntmp : tmp; + return 0; +} diff --git a/cstr_util.h b/cstr_util.h index bf7aa60..109a548 100644 --- a/cstr_util.h +++ b/cstr_util.h @@ -41,6 +41,49 @@ uint32_t cstr_read_uint32(const uint8_t* bytes, int big); * @return result */ int32_t cstr_read_int32(const uint8_t* bytes, int big); +/** + * @brief Convert string to lowercase + * @param str String needed to convert + * @param len The length of the string. If is 0, strlen will be called to calculate length. +*/ +void cstr_tolowercase2(char* str, size_t len); +/** + * @brief Convert bytes to uint64 + * @param bytes Bytes (at least 8 bytes) + * @param big 0 if little endian otherwise big endian + * @return result +*/ +uint64_t cstr_read_uint64(const uint8_t* bytes, int big); +/** + * @brief Convert bytes to int64 + * @param bytes Bytes (at least 8 bytes) + * @param big 0 if little endian otherwise big endian + * @return result +*/ +int64_t cstr_read_int64(const uint8_t* bytes, int big); +/** + * @brief Convert bytes to uint16 + * @param bytes Bytes (at least 2 bytes) + * @param big 0 if little endian otherwise big endian + * @return result +*/ +uint16_t cstr_read_uint16(const uint8_t* bytes, int big); +/** + * @brief Convert bytes to int16 + * @param bytes Bytes (at least 2 bytes) + * @param big 0 if little endian otherwise big endian + * @return result +*/ +int16_t cstr_read_int16(const uint8_t* bytes, int big); +/** + * @brief Read string from buffer + * @param buf Buffer + * @param dest Result string + * @param pos The start position in buffer. After a successed called, the position will be updated. + * @param buf_len The length of buffer + * @return 0 if successed otherwise 1 +*/ +int cstr_read_str(char* buf, char** dest, size_t* pos, size_t buf_len); #ifdef __cplusplus } #endif diff --git a/file_reader.c b/file_reader.c new file mode 100644 index 0000000..4691f80 --- /dev/null +++ b/file_reader.c @@ -0,0 +1,136 @@ +#include "file_reader.h" + +#include +#include +#include "cfileop.h" +#include "cstr_util.h" + +typedef struct file_reader_file { + FILE* f; + /// 0 if little endian otherwise big endian + unsigned char endian; +} file_reader_file; + +file_reader_file* create_file_reader(FILE* f, unsigned char endian) { + if (!f) return NULL; + file_reader_file* r = malloc(sizeof(file_reader_file)); + if (!r) return NULL; + r->f = f; + r->endian = endian; + return r; +} + +void free_file_reader(file_reader_file* f) { + if (!f) return; + free(f); +} + +void set_file_reader_endian(file_reader_file* f, unsigned char endian) { + if (!f) return; + f->endian = endian; +} + +int file_reader_read_int32(file_reader_file* f, int32_t* re) { + if (!f) return 1; + int64_t offset = fileop_ftell(f->f); + int32_t r = 0; + int origin = SEEK_SET; + if (offset == -1) { + origin = SEEK_CUR; + } + size_t c; + uint8_t buf[4]; + if ((c = fread(buf, 1, 4, f->f)) < 4) { + if (origin == SEEK_CUR) offset = -c; + fileop_fseek(f->f, offset, origin); + return 1; + } + r = cstr_read_int32(buf, f->endian); + if (re) *re = r; + return 0; +} + +int file_reader_read_uint32(file_reader_file* f, uint32_t* re) { + return file_reader_read_int32(f, (int32_t*)re); +} + +int file_reader_read_int64(file_reader_file* f, int64_t* re) { + if (!f) return 1; + int64_t offset = fileop_ftell(f->f), r = 0; + int origin = SEEK_SET; + if (offset == -1) { + origin = SEEK_CUR; + } + size_t c; + uint8_t buf[8]; + if ((c = fread(buf, 1, 8, f->f)) < 8) { + if (origin == SEEK_CUR) offset = -c; + fileop_fseek(f->f, offset, origin); + return 1; + } + r = cstr_read_int64(buf, f->endian); + if (re) *re = r; + return 0; +} + +int file_reader_read_str(file_reader_file* f, char** buf) { + if (!f) return 1; + char* b = NULL; + char bu[128]; + size_t blen = 128, n = 0, c = 0, tc = 0, pos = 0; + if (buf) { + b = malloc(blen); + if (!b) return 1; + } + int64_t offset = fileop_ftell(f->f); + int origin = SEEK_SET; + if (offset == -1) { + origin = SEEK_CUR; + } + while (1) { + if (n >= c) { + if (!(tc = fread(bu, 1, 128, f->f))) { + if (b) free(b); + if (origin == SEEK_CUR) { + offset = -c; + } + fileop_fseek(f->f, offset, origin); + return 1; + } + c += tc; + } + if (buf && n >= blen) { + size_t nlen = blen + 128; + char* nb = realloc(b, nlen); + if (!nb) { + if (b) free(b); + if (origin == SEEK_CUR) { + offset = -c; + } + fileop_fseek(f->f, offset, origin); + return 1; + } + b = nb; + blen = nlen; + } + pos = n - (c - tc); + if (buf && b) { + b[n] = bu[pos]; + } + if (bu[pos] == 0) { + break; + } + n++; + } + if (buf) { + char* nb = realloc(b, n + 1); + *buf = nb ? nb : b; + } + if (origin == SEEK_SET) { + offset += n + 1; + } else { + offset = -(c - n - 1); + } + fileop_fseek(f->f, offset, origin); + return 0; +} diff --git a/file_reader.h b/file_reader.h new file mode 100644 index 0000000..9c06019 --- /dev/null +++ b/file_reader.h @@ -0,0 +1,58 @@ +#ifndef _UTILS_FILE_READER_H +#define _UTILS_FILE_READER_H +#include +#include +#if __cplusplus +extern "C" { +#endif +typedef struct file_reader_file file_reader_file; +/** + * @brief Create a reader from a stream + * @param f File stream + * @param endian 0 if little endian otherwise big endian + * @return the reader, NULL if OOM or stream is NULL. +*/ +file_reader_file* create_file_reader(FILE* f, unsigned char endian); +/** + * @brief Free a reader. This will not close stream. + * @param f the pointer to reader struct +*/ +void free_file_reader(file_reader_file* f); +/** + * @brief Set endian for reader + * @param f reader + * @param endian 0 if little endian otherwise big endian +*/ +void set_file_reader_endian(file_reader_file* f, unsigned char endian); +/** + * @brief Read int32 from reader + * @param f reader + * @param re result + * @return 0 if successed otherwise 1 +*/ +int file_reader_read_int32(file_reader_file* f, int32_t* re); +/** + * @brief Read uint32 from reader + * @param f reader + * @param re result + * @return 0 if successed otherwise 1 +*/ +int file_reader_read_uint32(file_reader_file* f, uint32_t* re); +/** + * @brief Read int64 from reader + * @param f reader + * @param re result + * @return 0 if successed otherwise 1 +*/ +int file_reader_read_int64(file_reader_file* f, int64_t* re); +/** + * @brief Read 0 terminal string from reader + * @param f reader + * @param buf Result. Need free memory by using free. + * @return 0 if successed otherwise 1 +*/ +int file_reader_read_str(file_reader_file* f, char** buf); +#if __cplusplus +} +#endif +#endif