From e89f35aafeb7469d2fc255d4c56aa73a0cbb8c9d Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 12:15:54 -0600 Subject: [PATCH 01/21] Create dir.h --- code/logic/fossil/io/dir.h | 195 +++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 code/logic/fossil/io/dir.h diff --git a/code/logic/fossil/io/dir.h b/code/logic/fossil/io/dir.h new file mode 100644 index 0000000..e254c16 --- /dev/null +++ b/code/logic/fossil/io/dir.h @@ -0,0 +1,195 @@ +/** + * ----------------------------------------------------------------------------- + * Project: Fossil Logic + * + * This file is part of the Fossil Logic project, which aims to develop + * high-performance, cross-platform applications and libraries. The code + * contained herein is licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain + * a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Author: Michael Gene Brockus (Dreamer) + * Date: 04/05/2014 + * + * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. + * ----------------------------------------------------------------------------- + */ +#ifndef FOSSIL_IO_DIR_H +#define FOSSIL_IO_DIR_H + +#include "stream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ============================================================================ +// Directory Entry Structure +// ============================================================================ + +/** + * @brief Represents a directory entry (file, directory, symlink, etc.) + */ +typedef struct fossil_io_dir_entry_t { + char name[512]; ///< Entry name + char path[1024]; ///< Full resolved path + int32_t type; ///< 0=file, 1=dir, 2=symlink, 3=other + uint64_t size; ///< File size in bytes (0 for dirs) + uint64_t modified; ///< Last modified timestamp (UTC epoch) +} fossil_io_dir_entry_t; + + +// ============================================================================ +// Directory Iterator +// ============================================================================ + +/** + * @brief Represents an open directory iterator. + */ +typedef struct fossil_io_dir_iter_t { + void *handle; ///< Platform-specific DIR*/HANDLE + char basepath[1024]; ///< The directory being iterated + fossil_io_dir_entry_t current; + int32_t active; ///< 1=active, 0=end or closed +} fossil_io_dir_iter_t; + + +// ============================================================================ +// Basic Directory Operations +// ============================================================================ + +int32_t fossil_io_dir_exists(const char *path); +int32_t fossil_io_dir_create(const char *path); +int32_t fossil_io_dir_remove(const char *path); +int32_t fossil_io_dir_remove_recursive(const char *path); +int32_t fossil_io_dir_clear(const char *path); + +int32_t fossil_io_dir_copy(const char *src, const char *dst); +int32_t fossil_io_dir_copy_recursive(const char *src, const char *dst); + +int32_t fossil_io_dir_move(const char *src, const char *dst); +int32_t fossil_io_dir_rename(const char *oldpath, const char *newpath); + + +// ============================================================================ +// Directory Iteration API +// ============================================================================ + +int32_t fossil_io_dir_iter_open(fossil_io_dir_iter_t *it, const char *path); +int32_t fossil_io_dir_iter_next(fossil_io_dir_iter_t *it); ///< Returns 1 if valid, 0 if end +void fossil_io_dir_iter_close(fossil_io_dir_iter_t *it); + +int32_t fossil_io_dir_list(const char *path, + fossil_io_dir_entry_t *entries, + size_t *count, + size_t max_entries); + + +// ============================================================================ +// Path Utilities +// ============================================================================ + +int32_t fossil_io_dir_is_absolute(const char *path); +int32_t fossil_io_dir_join(const char *base, const char *name, char *out, size_t outsz); +int32_t fossil_io_dir_basename(const char *path, char *out, size_t outsz); +int32_t fossil_io_dir_dirname(const char *path, char *out, size_t outsz); +int32_t fossil_io_dir_normalize(const char *path, char *out, size_t outsz); +int32_t fossil_io_dir_realpath(const char *path, char *out, size_t outsz); + + +// ============================================================================ +// Directory Inspection Queries +// ============================================================================ + +int32_t fossil_io_dir_is_empty(const char *path); +int32_t fossil_io_dir_count(const char *path, size_t *count); +int32_t fossil_io_dir_size(const char *path, uint64_t *bytes); // recursive sum + +// ============================================================================ +// Filtering + Scanning +// ============================================================================ + +/** + * @brief Callback used for scanning files. + * Return 1 to continue, 0 to stop traversal. + */ +typedef int32_t (*fossil_io_dir_scan_callback)( + const fossil_io_dir_entry_t *entry, + void *userdata); + +int32_t fossil_io_dir_scan(const char *path, fossil_io_dir_scan_callback cb, void *userdata); +int32_t fossil_io_dir_scan_recursive(const char *path, fossil_io_dir_scan_callback cb, void *userdata); + + +// ============================================================================ +// Permissions (platform supported) +// ============================================================================ + +int32_t fossil_io_dir_set_permissions(const char *path, int32_t mode); +int32_t fossil_io_dir_get_permissions(const char *path, int32_t *mode); + + +// ============================================================================ +// Temp Directory Utilities +// ============================================================================ + +int32_t fossil_io_dir_temp(char *out, size_t outsz); +int32_t fossil_io_dir_create_temp(char *out, size_t outsz); + + +// ============================================================================ +// Metadata Queries +// ============================================================================ + +int32_t fossil_io_dir_get_modified(const char *path, uint64_t *timestamp); +int32_t fossil_io_dir_get_created(const char *path, uint64_t *timestamp); + + +// ============================================================================ +// Directory Sync / Backup +// ============================================================================ + +int32_t fossil_io_dir_backup(const char *src, const char *suffix); +int32_t fossil_io_dir_mirror(const char *src, const char *dst); +int32_t fossil_io_dir_sync(const char *src, const char *dst, int32_t delete_extraneous); + + +// ============================================================================ +// Low-Level Helpers +// ============================================================================ + +int32_t fossil_io_dir_is_directory(const char *path); +int32_t fossil_io_dir_is_file(const char *path); +int32_t fossil_io_dir_is_symlink(const char *path); + +#ifdef __cplusplus +} +#include + +/** + * Namespace for the Fossil Logic I/O library. + */ +namespace fossil { + + /** + * Namespace for the I/O utilities. + */ + namespace io { + + + + } + +} + +#endif + +#endif /* FOSSIL_IO_FRAMEWORK_H */ From b736bcb918015234954d7240c55b3be2ca1f7f5d Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:15:39 -0600 Subject: [PATCH 02/21] Create dir.c --- code/logic/dir.c | 995 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 995 insertions(+) create mode 100644 code/logic/dir.c diff --git a/code/logic/dir.c b/code/logic/dir.c new file mode 100644 index 0000000..2b2cc50 --- /dev/null +++ b/code/logic/dir.c @@ -0,0 +1,995 @@ +/** + * ----------------------------------------------------------------------------- + * Project: Fossil Logic + * + * This file is part of the Fossil Logic project, which aims to develop + * high-performance, cross-platform applications and libraries. The code + * contained herein is licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain + * a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Author: Michael Gene Brockus (Dreamer) + * Date: 04/05/2014 + * + * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. + * ----------------------------------------------------------------------------- + */ +#include "fossil/io/dir.h" +#include "fossil/io/cstring.h" +#include "fossil/io/output.h" + +#include +#include + +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #include + #include + #include + #define PATHSEP '\\' + #define PATHSEP_STR "\\" + #define mkdir_native(p,mode) _mkdir(p) + #define rmdir_native(p) _rmdir(p) + #define stat_native _stat + typedef struct _stat stat_t; +#else + #include + #include + #include + #include + #include + #define PATHSEP '/' + #define PATHSEP_STR "/" + #define mkdir_native(p,mode) mkdir((p),(mode)) + #define rmdir_native(p) rmdir(p) + #define stat_native stat + typedef struct stat stat_t; +#endif + +// ------------------------------------------------------------ +// Helpers +// ------------------------------------------------------------ +static void safe_strcpy(char *dst, const char *src, size_t dstlen){ + if (!dst || dstlen == 0) return; + if (!src) { dst[0] = '\0'; return; } + strncpy(dst, src, dstlen - 1); + dst[dstlen - 1] = '\0'; +} + +static int32_t join_paths(const char *a, const char *b, char *out, size_t outsz){ + if (!out || outsz == 0) return -1; + if (!a || !a[0]) { safe_strcpy(out, b ? b : "", outsz); return 0; } + if (!b || !b[0]) { safe_strcpy(out, a, outsz); return 0; } + + size_t la = strlen(a); + int need_sep = (a[la-1] != '/' && a[la-1] != '\\'); + +#ifdef _WIN32 + need_sep = (a[la-1] != '\\' && a[la-1] != '/'); +#endif + + if (need_sep) + snprintf(out, outsz, "%s%c%s", a, PATHSEP, b); + else + snprintf(out, outsz, "%s%s", a, b); + out[outsz-1] = '\0'; + return 0; +} + +static int32_t file_copy_internal(const char *src, const char *dst){ + if (!src || !dst) return -1; + FILE *fin = fopen(src, "rb"); + if (!fin) return -1; + FILE *fout = fopen(dst, "wb"); + if (!fout) { fclose(fin); return -1; } + + char buf[16384]; + size_t r; + int err = 0; + while ((r = fread(buf, 1, sizeof(buf), fin)) > 0){ + if (fwrite(buf, 1, r, fout) != r) { err = -1; break; } + } + + fclose(fin); + fclose(fout); + return err; +} + +static int32_t path_is_dot_or_dotdot(const char *p){ + if (!p) return 0; + return (strcmp(p, ".") == 0 || strcmp(p, "..") == 0); +} + +// ------------------------------------------------------------ +// Low-Level Helpers +// ------------------------------------------------------------ +int32_t fossil_io_dir_is_directory(const char *path){ + if (!path) return 0; + stat_t st; + if (stat_native(path, &st) != 0) return 0; +#ifdef _WIN32 + return (st.st_mode & _S_IFDIR) ? 1 : 0; +#else + return S_ISDIR(st.st_mode) ? 1 : 0; +#endif +} + +int32_t fossil_io_dir_is_file(const char *path){ + if (!path) return 0; + stat_t st; + if (stat_native(path, &st) != 0) return 0; +#ifdef _WIN32 + return (st.st_mode & _S_IFREG) ? 1 : 0; +#else + return S_ISREG(st.st_mode) ? 1 : 0; +#endif +} + +int32_t fossil_io_dir_is_symlink(const char *path){ + if (!path) return 0; +#ifndef _WIN32 + struct stat st; + if (lstat(path, &st) != 0) return 0; + return S_ISLNK(st.st_mode) ? 1 : 0; +#else + // Windows: best-effort using attributes + DWORD a = GetFileAttributesA(path); + if (a == INVALID_FILE_ATTRIBUTES) return 0; + return (a & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; +#endif +} + +// ------------------------------------------------------------ +// Basic Operations +// ------------------------------------------------------------ +int32_t fossil_io_dir_exists(const char *path){ + return fossil_io_dir_is_directory(path); +} + +int32_t fossil_io_dir_create(const char *path){ + if (!path) return -1; + // attempt to create parent directories as needed (mkdir -p style) + char tmp[1024]; + safe_strcpy(tmp, path, sizeof(tmp)); + size_t len = strlen(tmp); + if (len == 0) return -1; + + // Normalize separators to platform-specific + for (size_t i = 0; i < len; ++i){ +#ifdef _WIN32 + if (tmp[i] == '/') tmp[i] = '\\'; +#else + if (tmp[i] == '\\') tmp[i] = '/'; +#endif + } + + // create progressively + for (size_t i = 1; i <= len; ++i){ + if (tmp[i] == '\0' || tmp[i] == PATHSEP){ + char save = tmp[i]; + tmp[i] = '\0'; + if (!fossil_io_dir_exists(tmp)){ + int rc; +#ifdef _WIN32 + rc = mkdir_native(tmp); +#else + rc = mkdir_native(tmp, 0755); +#endif + if (rc != 0 && errno != EEXIST) { + tmp[i] = save; + return -1; + } + } + tmp[i] = save; + } + } + + // final create if not exists + if (!fossil_io_dir_exists(path)){ +#ifdef _WIN32 + if (mkdir_native(path) != 0 && errno != EEXIST) return -1; +#else + if (mkdir_native(path, 0755) != 0 && errno != EEXIST) return -1; +#endif + } + return 0; +} + +int32_t fossil_io_dir_remove(const char *path){ + if (!path) return -1; + if (!fossil_io_dir_exists(path)) return 0; +#ifdef _WIN32 + return rmdir_native(path) == 0 ? 0 : -1; +#else + return rmdir_native(path) == 0 ? 0 : -1; +#endif +} + +static int32_t remove_recursive_internal(const char *path){ + if (!path) return -1; + if (!fossil_io_dir_exists(path)) return 0; + +#ifndef _WIN32 + DIR *d = opendir(path); + if (!d) return -1; + struct dirent *ent; + char child[2048]; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + join_paths(path, ent->d_name, child, sizeof(child)); + if (fossil_io_dir_is_directory(child)){ + if (remove_recursive_internal(child) != 0) { closedir(d); return -1; } + } else { + if (remove(child) != 0) { closedir(d); return -1; } + } + } + closedir(d); + if (rmdir(path) != 0) return -1; + return 0; +#else + WIN32_FIND_DATAA fd; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", path); + HANDLE h = FindFirstFileA(search, &fd); + if (h == INVALID_HANDLE_VALUE) return -1; + do { + const char *name = fd.cFileName; + if (path_is_dot_or_dotdot(name)) continue; + char child[MAX_PATH]; + snprintf(child, sizeof(child), "%s\\%s", path, name); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ + if (remove_recursive_internal(child) != 0) { FindClose(h); return -1; } + } else { + if (!DeleteFileA(child)) { FindClose(h); return -1; } + } + } while (FindNextFileA(h, &fd)); + FindClose(h); + if (!RemoveDirectoryA(path)) return -1; + return 0; +#endif +} + +int32_t fossil_io_dir_remove_recursive(const char *path){ + return remove_recursive_internal(path); +} + +int32_t fossil_io_dir_clear(const char *path){ + // Remove contents but keep dir + if (!path) return -1; + if (!fossil_io_dir_exists(path)) return 0; + +#ifndef _WIN32 + DIR *d = opendir(path); + if (!d) return -1; + struct dirent *ent; + char child[2048]; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + join_paths(path, ent->d_name, child, sizeof(child)); + if (fossil_io_dir_is_directory(child)){ + if (remove_recursive_internal(child) != 0) { closedir(d); return -1; } + } else { + if (remove(child) != 0) { closedir(d); return -1; } + } + } + closedir(d); + return 0; +#else + WIN32_FIND_DATAA fd; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", path); + HANDLE h = FindFirstFileA(search, &fd); + if (h == INVALID_HANDLE_VALUE) return -1; + do { + const char *name = fd.cFileName; + if (path_is_dot_or_dotdot(name)) continue; + char child[MAX_PATH]; + snprintf(child, sizeof(child), "%s\\%s", path, name); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ + if (remove_recursive_internal(child) != 0) { FindClose(h); return -1; } + } else { + if (!DeleteFileA(child)) { FindClose(h); return -1; } + } + } while (FindNextFileA(h, &fd)); + FindClose(h); + return 0; +#endif +} + +// Copy directory shallow +int32_t fossil_io_dir_copy(const char *src, const char *dst){ + if (!src || !dst) return -1; + if (!fossil_io_dir_exists(src)) return -1; + fossil_io_dir_create(dst); + +#ifndef _WIN32 + DIR *d = opendir(src); + if (!d) return -1; + struct dirent *ent; + char schild[2048], dchild[2048]; + int rc = 0; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + join_paths(src, ent->d_name, schild, sizeof(schild)); + join_paths(dst, ent->d_name, dchild, sizeof(dchild)); + if (fossil_io_dir_is_directory(schild)){ + // create subdir only (not recursive) + fossil_io_dir_create(dchild); + } else { + if (file_copy_internal(schild, dchild) != 0) { rc = -1; break; } + } + } + closedir(d); + return rc; +#else + WIN32_FIND_DATAA fd; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", src); + HANDLE h = FindFirstFileA(search, &fd); + if (h == INVALID_HANDLE_VALUE) return -1; + int rc = 0; + do { + const char *name = fd.cFileName; + if (path_is_dot_or_dotdot(name)) continue; + char schild[MAX_PATH], dchild[MAX_PATH]; + snprintf(schild, sizeof(schild), "%s\\%s", src, name); + snprintf(dchild, sizeof(dchild), "%s\\%s", dst, name); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ + fossil_io_dir_create(dchild); + } else { + if (file_copy_internal(schild, dchild) != 0) { rc = -1; break; } + } + } while (FindNextFileA(h, &fd)); + FindClose(h); + return rc; +#endif +} + +static int32_t copy_recursive_internal(const char *src, const char *dst){ + if (!src || !dst) return -1; + if (!fossil_io_dir_exists(src)) return -1; + fossil_io_dir_create(dst); + +#ifndef _WIN32 + DIR *d = opendir(src); + if (!d) return -1; + struct dirent *ent; + char schild[2048], dchild[2048]; + int rc = 0; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + join_paths(src, ent->d_name, schild, sizeof(schild)); + join_paths(dst, ent->d_name, dchild, sizeof(dchild)); + if (fossil_io_dir_is_directory(schild)){ + if (copy_recursive_internal(schild, dchild) != 0) { rc = -1; break; } + } else { + if (file_copy_internal(schild, dchild) != 0) { rc = -1; break; } + } + } + closedir(d); + return rc; +#else + WIN32_FIND_DATAA fd; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", src); + HANDLE h = FindFirstFileA(search, &fd); + if (h == INVALID_HANDLE_VALUE) return -1; + int rc = 0; + do { + const char *name = fd.cFileName; + if (path_is_dot_or_dotdot(name)) continue; + char schild[MAX_PATH], dchild[MAX_PATH]; + snprintf(schild, sizeof(schild), "%s\\%s", src, name); + snprintf(dchild, sizeof(dchild), "%s\\%s", dst, name); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ + if (copy_recursive_internal(schild, dchild) != 0) { rc = -1; break; } + } else { + if (file_copy_internal(schild, dchild) != 0) { rc = -1; break; } + } + } while (FindNextFileA(h, &fd)); + FindClose(h); + return rc; +#endif +} + +int32_t fossil_io_dir_copy_recursive(const char *src, const char *dst){ + return copy_recursive_internal(src, dst); +} + +int32_t fossil_io_dir_move(const char *src, const char *dst){ + if (!src || !dst) return -1; +#ifdef _WIN32 + if (MoveFileA(src, dst)) return 0; + // if MoveFileA failed, attempt copy+delete + if (file_copy_internal(src, dst) == 0){ + if (DeleteFileA(src)) return 0; + return -1; + } + return -1; +#else + if (rename(src, dst) == 0) return 0; + // fallback: copy then remove + if (file_copy_internal(src, dst) == 0){ + if (remove(src) == 0) return 0; + return -1; + } + return -1; +#endif +} + +int32_t fossil_io_dir_rename(const char *oldpath, const char *newpath){ + if (!oldpath || !newpath) return -1; + if (rename(oldpath, newpath) == 0) return 0; + return -1; +} + +// ------------------------------------------------------------ +// Directory Iterator + Listing +// ------------------------------------------------------------ +int32_t fossil_io_dir_iter_open(fossil_io_dir_iter_t *it, const char *path){ + if (!it || !path) return -1; + memset(it, 0, sizeof(*it)); + safe_strcpy(it->basepath, path, sizeof(it->basepath)); + it->active = 0; + +#ifndef _WIN32 + DIR *d = opendir(path); + if (!d) return -1; + it->handle = d; + it->active = 1; + return 0; +#else + // Windows: store search handle in handle and preload first + WIN32_FIND_DATAA *fd = (WIN32_FIND_DATAA*)malloc(sizeof(WIN32_FIND_DATAA)); + if (!fd) return -1; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", path); + HANDLE h = FindFirstFileA(search, fd); + if (h == INVALID_HANDLE_VALUE) { free(fd); return -1; } + // store a small struct that includes handle and last data + struct { + HANDLE handle; + WIN32_FIND_DATAA data; + int has_current; + } *wh = malloc(sizeof(*wh)); + if (!wh) { FindClose(h); free(fd); return -1; } + wh->handle = h; + wh->data = *fd; + wh->has_current = 1; + free(fd); + it->handle = wh; + it->active = 1; + return 0; +#endif +} + +int32_t fossil_io_dir_iter_next(fossil_io_dir_iter_t *it){ + if (!it || !it->handle || !it->active) return 0; + +#ifndef _WIN32 + DIR *d = (DIR*)it->handle; + struct dirent *ent; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + safe_strcpy(it->current.name, ent->d_name, sizeof(it->current.name)); + join_paths(it->basepath, ent->d_name, it->current.path, sizeof(it->current.path)); + // fill type, size, modified + stat_t st; + if (stat_native(it->current.path, &st) == 0){ +#ifdef _WIN32 + it->current.type = (st.st_mode & _S_IFDIR) ? 1 : 0; +#else + if (S_ISDIR(st.st_mode)) it->current.type = 1; + else if (S_ISLNK(st.st_mode)) it->current.type = 2; + else if (S_ISREG(st.st_mode)) it->current.type = 0; + else it->current.type = 3; +#endif + it->current.size = (uint64_t)st.st_size; + it->current.modified = (uint64_t)st.st_mtime; + } else { + it->current.type = 3; + it->current.size = 0; + it->current.modified = 0; + } + return 1; + } + // end + return 0; +#else + // Windows: our handle object + struct { + HANDLE handle; + WIN32_FIND_DATAA data; + int has_current; + } *wh = (void*)it->handle; + + while (wh && wh->has_current){ + const char *name = wh->data.cFileName; + wh->has_current = 0; // consume current + if (!path_is_dot_or_dotdot(name)){ + safe_strcpy(it->current.name, name, sizeof(it->current.name)); + snprintf(it->current.path, sizeof(it->current.path), "%s\\%s", it->basepath, name); + if (wh->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) it->current.type = 1; + else it->current.type = 0; + // size (DWORD/FILETIME conversion) + uint64_t size = ((uint64_t)wh->data.nFileSizeHigh << 32) | wh->data.nFileSizeLow; + it->current.size = size; + // convert FILETIME to time_t (approx) + FILETIME ft = wh->data.ftLastWriteTime; + ULARGE_INTEGER ull; + ull.LowPart = ft.dwLowDateTime; + ull.HighPart = ft.dwHighDateTime; + // Windows epoch is 100-ns since Jan 1 1601. Convert to Unix epoch. + uint64_t windows_time = ull.QuadPart; + // 11644473600 seconds between epochs + uint64_t seconds = (windows_time / 10000000ULL) - 11644473600ULL; + it->current.modified = seconds; + // prepare next + if (FindNextFileA(wh->handle, &wh->data)) wh->has_current = 1; + return 1; + } + // get next + if (FindNextFileA(wh->handle, &wh->data)) wh->has_current = 1; + } + return 0; +#endif +} + +void fossil_io_dir_iter_close(fossil_io_dir_iter_t *it){ + if (!it || !it->handle) return; +#ifndef _WIN32 + DIR *d = (DIR*)it->handle; + closedir(d); + it->handle = NULL; + it->active = 0; +#else + struct { + HANDLE handle; + WIN32_FIND_DATAA data; + int has_current; + } *wh = (void*)it->handle; + if (wh){ + FindClose(wh->handle); + free(wh); + } + it->handle = NULL; + it->active = 0; +#endif +} + +int32_t fossil_io_dir_list(const char *path, + fossil_io_dir_entry_t *entries, + size_t *count, + size_t max_entries) +{ + if (!path || !entries || !count) return -1; + fossil_io_dir_iter_t it; + if (fossil_io_dir_iter_open(&it, path) != 0) return -1; + size_t idx = 0; + while (idx < max_entries && fossil_io_dir_iter_next(&it)){ + entries[idx++] = it.current; + } + fossil_io_dir_iter_close(&it); + *count = idx; + return 0; +} + +// ------------------------------------------------------------ +// Path utilities +// ------------------------------------------------------------ +int32_t fossil_io_dir_is_absolute(const char *path){ + if (!path || !path[0]) return 0; +#ifdef _WIN32 + // e.g., C:\ or \\server\share + if ((strlen(path) >= 2 && path[1] == ':') || (strlen(path) >= 2 && path[0] == '\\' && path[1] == '\\')) + return 1; + return 0; +#else + return (path[0] == '/') ? 1 : 0; +#endif +} + +int32_t fossil_io_dir_join(const char *base, const char *name, char *out, size_t outsz){ + if (!out || outsz == 0) return -1; + return join_paths(base, name, out, outsz); +} + +int32_t fossil_io_dir_basename(const char *path, char *out, size_t outsz){ + if (!path || !out) return -1; + const char *p = path + strlen(path); + while (p > path && (*p == '\\' || *p == '/')) --p; + const char *end = p; + while (p > path && *(p-1) != '\\' && *(p-1) != '/') --p; + size_t len = end - p + 1; + if (len >= outsz) len = outsz - 1; + strncpy(out, p, len); + out[len] = '\0'; + return 0; +} + +int32_t fossil_io_dir_dirname(const char *path, char *out, size_t outsz){ + if (!path || !out) return -1; + const char *p = path + strlen(path); + while (p > path && (*p == '\\' || *p == '/')) --p; + while (p > path && *(p-1) != '\\' && *(p-1) != '/') --p; + if (p == path){ + // no directory portion + safe_strcpy(out, ".", outsz); + return 0; + } + size_t len = p - path - 1; + if (len >= outsz) len = outsz - 1; + strncpy(out, path, len); + out[len] = '\0'; + return 0; +} + +int32_t fossil_io_dir_normalize(const char *path, char *out, size_t outsz){ + if (!path || !out) return -1; + // Very simple normalization: collapse duplicate separators and remove trailing separators (except root) + size_t j = 0; + int last_sep = 0; + for (size_t i = 0; path[i] != '\0' && j + 1 < outsz; ++i){ + char c = path[i]; + if (c == '/' || c == '\\'){ + if (last_sep) continue; + out[j++] = PATHSEP; + last_sep = 1; + } else { + out[j++] = c; + last_sep = 0; + } + } + // remove trailing separator if not root + if (j > 1 && out[j-1] == PATHSEP) j--; + out[j] = '\0'; + return 0; +} + +int32_t fossil_io_dir_realpath(const char *path, char *out, size_t outsz){ + if (!path || !out) return -1; +#ifdef _WIN32 + // use GetFullPathNameA + DWORD r = GetFullPathNameA(path, (DWORD)outsz, out, NULL); + return (r > 0 && r < outsz) ? 0 : -1; +#else + char buf[PATH_MAX]; + if (realpath(path, buf) == NULL) return -1; + safe_strcpy(out, buf, outsz); + return 0; +#endif +} + +// ------------------------------------------------------------ +// Inspection and counting +// ------------------------------------------------------------ +int32_t fossil_io_dir_is_empty(const char *path){ + if (!path) return -1; + if (!fossil_io_dir_exists(path)) return -1; +#ifndef _WIN32 + DIR *d = opendir(path); + if (!d) return -1; + struct dirent *ent; + int empty = 1; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + empty = 0; break; + } + closedir(d); + return empty; +#else + WIN32_FIND_DATAA fd; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", path); + HANDLE h = FindFirstFileA(search, &fd); + if (h == INVALID_HANDLE_VALUE) return -1; + int empty = 1; + do { + if (!path_is_dot_or_dotdot(fd.cFileName)) { empty = 0; break; } + } while (FindNextFileA(h, &fd)); + FindClose(h); + return empty; +#endif +} + +int32_t fossil_io_dir_count(const char *path, size_t *count){ + if (!path || !count) return -1; + if (!fossil_io_dir_exists(path)) return -1; + size_t c = 0; +#ifndef _WIN32 + DIR *d = opendir(path); + if (!d) return -1; + struct dirent *ent; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + ++c; + } + closedir(d); +#else + WIN32_FIND_DATAA fd; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", path); + HANDLE h = FindFirstFileA(search, &fd); + if (h == INVALID_HANDLE_VALUE) return -1; + do { + if (!path_is_dot_or_dotdot(fd.cFileName)) ++c; + } while (FindNextFileA(h, &fd)); + FindClose(h); +#endif + *count = c; + return 0; +} + +static int32_t size_recursive_internal(const char *path, uint64_t *acc){ + if (!path || !acc) return -1; +#ifndef _WIN32 + DIR *d = opendir(path); + if (!d) return -1; + struct dirent *ent; + char child[2048]; + while ((ent = readdir(d)) != NULL){ + if (path_is_dot_or_dotdot(ent->d_name)) continue; + join_paths(path, ent->d_name, child, sizeof(child)); + if (fossil_io_dir_is_directory(child)){ + if (size_recursive_internal(child, acc) != 0) { closedir(d); return -1; } + } else { + stat_t st; + if (stat_native(child, &st) == 0) *acc += (uint64_t)st.st_size; + } + } + closedir(d); + return 0; +#else + WIN32_FIND_DATAA fd; + char search[MAX_PATH]; + snprintf(search, sizeof(search), "%s\\*", path); + HANDLE h = FindFirstFileA(search, &fd); + if (h == INVALID_HANDLE_VALUE) return -1; + do { + const char *name = fd.cFileName; + if (path_is_dot_or_dotdot(name)) continue; + char child[MAX_PATH]; + snprintf(child, sizeof(child), "%s\\%s", path, name); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ + if (size_recursive_internal(child, acc) != 0) { FindClose(h); return -1; } + } else { + uint64_t size = ((uint64_t)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; + *acc += size; + } + } while (FindNextFileA(h, &fd)); + FindClose(h); + return 0; +#endif +} + +int32_t fossil_io_dir_size(const char *path, uint64_t *bytes){ + if (!path || !bytes) return -1; + *bytes = 0; + if (fossil_io_dir_is_file(path)){ + stat_t st; + if (stat_native(path, &st) != 0) return -1; + *bytes = (uint64_t)st.st_size; + return 0; + } + if (!fossil_io_dir_is_directory(path)) return -1; + return size_recursive_internal(path, bytes); +} + +// ------------------------------------------------------------ +// Scan + recursive scan +// ------------------------------------------------------------ +int32_t fossil_io_dir_scan(const char *path, fossil_io_dir_scan_callback cb, void *userdata){ + if (!path || !cb) return -1; + fossil_io_dir_iter_t it; + if (fossil_io_dir_iter_open(&it, path) != 0) return -1; + while (fossil_io_dir_iter_next(&it)){ + if (!cb(&it.current, userdata)) break; + } + fossil_io_dir_iter_close(&it); + return 0; +} + +static int32_t scan_recursive_internal(const char *path, fossil_io_dir_scan_callback cb, void *userdata){ + if (!path || !cb) return -1; + fossil_io_dir_iter_t it; + if (fossil_io_dir_iter_open(&it, path) != 0) return -1; + while (fossil_io_dir_iter_next(&it)){ + // invoke callback + if (!cb(&it.current, userdata)) { fossil_io_dir_iter_close(&it); return 0; } + // if directory, recurse + if (it.current.type == 1){ + if (scan_recursive_internal(it.current.path, cb, userdata) != 0) { fossil_io_dir_iter_close(&it); return -1; } + } + } + fossil_io_dir_iter_close(&it); + return 0; +} + +int32_t fossil_io_dir_scan_recursive(const char *path, fossil_io_dir_scan_callback cb, void *userdata){ + return scan_recursive_internal(path, cb, userdata); +} + +// ------------------------------------------------------------ +// Permissions +// ------------------------------------------------------------ +int32_t fossil_io_dir_set_permissions(const char *path, int32_t mode){ + if (!path) return -1; +#ifndef _WIN32 + if (chmod(path, (mode_t)mode) == 0) return 0; + return -1; +#else + // Windows: best-effort - set read-only attribute if write bit not provided + DWORD attrs = GetFileAttributesA(path); + if (attrs == INVALID_FILE_ATTRIBUTES) return -1; + if ((mode & 0222) == 0) attrs |= FILE_ATTRIBUTE_READONLY; + else attrs &= ~FILE_ATTRIBUTE_READONLY; + if (!SetFileAttributesA(path, attrs)) return -1; + return 0; +#endif +} + +int32_t fossil_io_dir_get_permissions(const char *path, int32_t *mode){ + if (!path || !mode) return -1; +#ifndef _WIN32 + struct stat st; + if (stat_native(path, &st) != 0) return -1; + *mode = st.st_mode & 0777; + return 0; +#else + DWORD attrs = GetFileAttributesA(path); + if (attrs == INVALID_FILE_ATTRIBUTES) return -1; + // Map readonly attribute to POSIX-ish mode + if (attrs & FILE_ATTRIBUTE_READONLY) *mode = 0444; + else *mode = 0666; + return 0; +#endif +} + +// ------------------------------------------------------------ +// Temp directory utilities +// ------------------------------------------------------------ +int32_t fossil_io_dir_temp(char *out, size_t outsz){ + if (!out) return -1; +#ifdef _WIN32 + DWORD r = GetTempPathA((DWORD)outsz, out); + return (r > 0 && r < outsz) ? 0 : -1; +#else + const char *t = getenv("TMPDIR"); + if (!t) t = "/tmp"; + safe_strcpy(out, t, outsz); + return 0; +#endif +} + +int32_t fossil_io_dir_create_temp(char *out, size_t outsz){ + if (!out) return -1; + char tmpdir[512]; + if (fossil_io_dir_temp(tmpdir, sizeof(tmpdir)) != 0) return -1; +#ifdef _WIN32 + char tpl[MAX_PATH]; + snprintf(tpl, sizeof(tpl), "%s\\fossil_tmp_XXXXXX", tmpdir); + // _mktemp_s modifies tpl in-place; create directory + if (_mktemp_s(tpl, sizeof(tpl)) != 0) return -1; + if (_mkdir(tpl) != 0) return -1; + safe_strcpy(out, tpl, outsz); + return 0; +#else + char tpl[PATH_MAX]; + snprintf(tpl, sizeof(tpl), "%s/fossil_tmp_XXXXXX", tmpdir); + char *r = mkdtemp(tpl); + if (!r) return -1; + safe_strcpy(out, r, outsz); + return 0; +#endif +} + +// ------------------------------------------------------------ +// Metadata +// ------------------------------------------------------------ +int32_t fossil_io_dir_get_modified(const char *path, uint64_t *timestamp){ + if (!path || !timestamp) return -1; + stat_t st; + if (stat_native(path, &st) != 0) return -1; + *timestamp = (uint64_t)st.st_mtime; + return 0; +} + +int32_t fossil_io_dir_get_created(const char *path, uint64_t *timestamp){ + if (!path || !timestamp) return -1; +#ifndef _WIN32 + // POSIX does not generally expose creation time; return ctime as approximation + stat_t st; + if (stat_native(path, &st) != 0) return -1; +#ifdef __APPLE__ + *timestamp = (uint64_t)st.st_birthtimespec.tv_sec; +#else + *timestamp = (uint64_t)st.st_ctime; +#endif + return 0; +#else + WIN32_FILE_ATTRIBUTE_DATA fad; + if (!GetFileAttributesExA(path, GetFileExInfoStandard, &fad)) return -1; + ULARGE_INTEGER ull; + ull.LowPart = fad.ftCreationTime.dwLowDateTime; + ull.HighPart = fad.ftCreationTime.dwHighDateTime; + uint64_t seconds = (ull.QuadPart / 10000000ULL) - 11644473600ULL; + *timestamp = seconds; + return 0; +#endif +} + +// ------------------------------------------------------------ +// Backup / mirror / sync (basic implementations) +// ------------------------------------------------------------ +int32_t fossil_io_dir_backup(const char *src, const char *suffix){ + if (!src || !suffix) return -1; + char dst[2048]; + snprintf(dst, sizeof(dst), "%s%s", src, suffix); + return fossil_io_dir_copy_recursive(src, dst); +} + +int32_t fossil_io_dir_mirror(const char *src, const char *dst){ + if (!src || !dst) return -1; + // naive mirror: if dst exists remove and copy recursive + if (fossil_io_dir_exists(dst)) { + if (fossil_io_dir_remove_recursive(dst) != 0) return -1; + } + return fossil_io_dir_copy_recursive(src, dst); +} + +static int32_t sync_internal_delete_extraneous(const char *src, const char *dst){ + // delete files in dst that are not in src + if (!src || !dst) return -1; + fossil_io_dir_iter_t it; + if (fossil_io_dir_iter_open(&it, dst) != 0) return -1; + char srcchild[2048], dstchild[2048]; + while (fossil_io_dir_iter_next(&it)){ + join_paths(src, it.current.name, srcchild, sizeof(srcchild)); + join_paths(dst, it.current.name, dstchild, sizeof(dstchild)); + if (!fossil_io_dir_is_directory(srcchild) && !fossil_io_dir_is_file(srcchild)){ + // not present in src => remove from dst (recursively) + if (it.current.type == 1) fossil_io_dir_remove_recursive(dstchild); + else remove(dstchild); + } else { + // present, recurse for directories + if (it.current.type == 1) sync_internal_delete_extraneous(srcchild, dstchild); + } + } + fossil_io_dir_iter_close(&it); + return 0; +} + +int32_t fossil_io_dir_sync(const char *src, const char *dst, int32_t delete_extraneous){ + if (!src || !dst) return -1; + if (!fossil_io_dir_exists(src)) return -1; + fossil_io_dir_create(dst); + + // copy entries from src to dst (overwrite) + fossil_io_dir_iter_t it; + if (fossil_io_dir_iter_open(&it, src) != 0) return -1; + char srcchild[2048], dstchild[2048]; + while (fossil_io_dir_iter_next(&it)){ + join_paths(src, it.current.name, srcchild, sizeof(srcchild)); + join_paths(dst, it.current.name, dstchild, sizeof(dstchild)); + if (it.current.type == 1){ + fossil_io_dir_sync(srcchild, dstchild, delete_extraneous); + } else { + // simple copy (overwrite) + file_copy_internal(srcchild, dstchild); + } + } + fossil_io_dir_iter_close(&it); + + if (delete_extraneous){ + sync_internal_delete_extraneous(src, dst); + } + return 0; +} From 31b95c02b7abd23d173e05ae20c098a0b8bb5612 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:17:19 -0600 Subject: [PATCH 03/21] Update meson.build --- code/logic/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/logic/meson.build b/code/logic/meson.build index 2802228..4f6c4b6 100644 --- a/code/logic/meson.build +++ b/code/logic/meson.build @@ -5,13 +5,13 @@ add_project_arguments('-D_POSIX_C_SOURCE=200112L', language: 'cpp') fossil_io_lib = library('fossil_io', files( - 'parser.c', 'archive.c', 'input.c', 'output.c', 'error.c', 'soap.c', 'stream.c', + 'dir.c', 'cstring.c' ), install: true, From 7197afc94095fc3b10ecae7ae7014ee0c9b4e284 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:18:13 -0800 Subject: [PATCH 04/21] Delete code/logic/parser.c --- code/logic/parser.c | 869 -------------------------------------------- 1 file changed, 869 deletions(-) delete mode 100644 code/logic/parser.c diff --git a/code/logic/parser.c b/code/logic/parser.c deleted file mode 100644 index c01855e..0000000 --- a/code/logic/parser.c +++ /dev/null @@ -1,869 +0,0 @@ -/** - * ----------------------------------------------------------------------------- - * Project: Fossil Logic - * - * This file is part of the Fossil Logic project, which aims to develop - * high-performance, cross-platform applications and libraries. The code - * contained herein is licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain - * a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * Author: Michael Gene Brockus (Dreamer) - * Date: 04/05/2014 - * - * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. - * ----------------------------------------------------------------------------- - */ -#include "fossil/io/parser.h" -#include "fossil/io/output.h" -#include "fossil/io/cstring.h" -#include -#include -#include -#include -#include -#include - -#define DP(i, j) dp[(i) * (len2 + 1) + (j)] - -int FOSSIL_CLI_TOGGLE_DRY_RUN = 0; -int FOSSIL_CLI_TOGGLE_VERBOSE = 0; - -char *FOSSIL_CLI_TOOL_NAME = "fossil-cli"; -char *FOSSIL_CLI_TOOL_VERSION = "1.0.0"; - -#ifdef _WIN32 -#include -#define isatty _isatty -#ifndef STDOUT_FILENO -#define STDOUT_FILENO _fileno(stdout) -#endif -#else -#include -#endif - -extern char *_custom_strdup(const char *str) { - if (!str) return NULL; - size_t len = strlen(str) + 1; - char *dup = malloc(len); - if (dup) { - memcpy(dup, str, len); - } - return dup; -} - -// ================================================================== -// TI Reasoning Metadata (lightweight struct for audit/debug) -// ================================================================== -typedef struct { - const char *input; - const char *suggested; - int edit_distance; - float confidence_score; // 0.0 to 1.0 - const char *reason; -} fossil_ti_reason_t; - -// ================================================================== -// Levenshtein Distance (Unchanged Core) -// ================================================================== -int levenshtein_distance(const char *s1, const char *s2) { - if (!s1 || !s2) return INT_MAX; - - int len1 = (int)strlen(s1), len2 = (int)strlen(s2); - int i, j; - - int *dp = (int *)calloc((size_t)(len1 + 1) * (size_t)(len2 + 1), sizeof(int)); - if (!dp) return INT_MAX; - - for (i = 0; i <= len1; i++) DP(i, 0) = i; - for (j = 0; j <= len2; j++) DP(0, j) = j; - - for (i = 1; i <= len1; i++) { - for (j = 1; j <= len2; j++) { - int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1; - int del = DP(i - 1, j) + 1; - int ins = DP(i, j - 1) + 1; - int sub = DP(i - 1, j - 1) + cost; - int min = del < ins ? del : ins; - min = min < sub ? min : sub; - DP(i, j) = min; - } - } - - int result = DP(len1, len2); - free(dp); - return result; -} - -// ================================================================== -// TI-Aware Command Suggestion (with traceable reasoning) -// ================================================================== -const char* suggest_command_ti(const char *input, fossil_io_parser_palette_t *palette, fossil_ti_reason_t *out_reason) { - if (!input || !palette) return NULL; - - fossil_io_parser_command_t *current = palette->commands; - const char *best_match = NULL; - int min_distance = INT_MAX; - int best_length = 1; // Avoid divide-by-zero - - while (current) { - if (current->name) { - int distance = levenshtein_distance(input, current->name); - if (distance < min_distance) { - min_distance = distance; - best_match = current->name; - best_length = (int)strlen(current->name); - } - } - current = current->next; - } - - if (!best_match) return NULL; - - // Compute confidence score based on edit distance - float confidence = 1.0f - ((float)min_distance / (float)best_length); - confidence = (confidence < 0.0f) ? 0.0f : (confidence > 1.0f) ? 1.0f : confidence; - - // Optional reasoning trace - if (out_reason) { - out_reason->input = input; - out_reason->suggested = best_match; - out_reason->edit_distance = min_distance; - out_reason->confidence_score = confidence; - out_reason->reason = (confidence >= 0.7f) ? "Close semantic match" : "Low confidence match"; - } - - // Only return suggestions above a minimum confidence threshold - return (confidence >= 0.7f) ? best_match : NULL; -} - -// ================================================================== -// Functions -// ================================================================== - -void show_version(void) { - fossil_io_printf("{blue}Version:{reset} %s\n", FOSSIL_CLI_TOOL_VERSION); -} - -void show_help(const char *command_name, const fossil_io_parser_palette_t *palette) { - if (!palette) return; - - fossil_io_parser_command_t *command = palette->commands; - - // If no specific command is provided, show all commands - if (!command_name) { - fossil_io_printf("{blue}Available commands:{reset}\n"); - while (command) { - if (command->name && command->description) { - fossil_io_printf("{cyan} %s: %s{reset}\n", command->name, command->description); - } - command = command->next; - } - fossil_io_printf("\n{blue}Use '--help ' for details on a specific command.{reset}\n"); - return; - } - - // Search for the specific command - while (command) { - if (command->name && strcmp(command->name, command_name) == 0) { - fossil_io_printf("{blue}Command: %s\nDescription: %s{reset}\n", - command->name, command->description ? command->description : "No description available"); - fossil_io_printf("{blue}Arguments:{reset}\n"); - fossil_io_parser_argument_t *arg = command->arguments; - while (arg) { - if (arg->name) { - fossil_io_printf("{cyan} --%s (%s): ", - arg->name, - arg->type == FOSSIL_IO_PARSER_BOOL ? "bool" : - arg->type == FOSSIL_IO_PARSER_STRING ? "string" : - arg->type == FOSSIL_IO_PARSER_INT ? "int" : - arg->type == FOSSIL_IO_PARSER_FLOAT ? "float" : - arg->type == FOSSIL_IO_PARSER_DATE ? "date" : - arg->type == FOSSIL_IO_PARSER_ARRAY ? "array" : - arg->type == FOSSIL_IO_PARSER_FEATURE ? "feature" : - arg->type == FOSSIL_IO_PARSER_INVALID ? "invalid" : - "unknown"); - - if (arg->value) { - switch (arg->type) { - case FOSSIL_IO_PARSER_BOOL: - case FOSSIL_IO_PARSER_FEATURE: - fossil_io_printf("%s", (*(int *)arg->value) ? "true" : "false"); - break; - case FOSSIL_IO_PARSER_INT: - fossil_io_printf("%d", *(int *)arg->value); - break; - case FOSSIL_IO_PARSER_FLOAT: - fossil_io_printf("%f", *(float *)arg->value); - break; - case FOSSIL_IO_PARSER_STRING: - case FOSSIL_IO_PARSER_DATE: - fossil_io_printf("%s", (char *)arg->value); - break; - case FOSSIL_IO_PARSER_ARRAY: { - char **arr = (char **)arg->value; - int idx = 0; - fossil_io_printf("["); - while (arr && arr[idx]) { - fossil_io_printf("%s%s", idx > 0 ? ", " : "", arr[idx]); - idx++; - } - fossil_io_printf("]"); - break; - } - default: - fossil_io_printf("Unknown"); - break; - } - } else { - fossil_io_printf("No default value"); - } - fossil_io_printf("{reset}\n"); - } - arg = arg->next; - } - - // Handle specific flags - fossil_io_printf("{blue}Built-in:{reset}\n"); - fossil_io_printf("{cyan} --help: Show help information for this command.{reset}\n"); - fossil_io_printf("{cyan} --version: Display the version of the application.{reset}\n"); - fossil_io_printf("{cyan} --dry-run: Simulate the operation without making changes.{reset}\n"); - fossil_io_printf("{cyan} --verbose: Provide detailed output during execution.{reset}\n"); - fossil_io_printf("{cyan} --color=[enable|disable|auto]: Control colored output (default: auto).{reset}\n"); - return; - } - command = command->next; - } - - // If the command is not found - fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown command '%s'. Use '--help' to see available commands.{reset}\n", command_name); -} - -void show_usage(const char *command_name, const fossil_io_parser_palette_t *palette) { - if (!palette || !command_name) return; - - fossil_io_parser_command_t *command = palette->commands; - - // Search for the specific command - while (command) { - if (command->name && strcmp(command->name, command_name) == 0) { - fossil_io_printf("{blue}Usage example for '%s':{reset}\n", command->name); - fossil_io_printf("{cyan} %s{reset}", command->name); - - fossil_io_parser_argument_t *arg = command->arguments; - while (arg) { - if (arg->name) { - fossil_io_printf("{cyan} --%s {reset}", arg->name); - switch (arg->type) { - case FOSSIL_IO_PARSER_STRING: - fossil_io_printf("{cyan}{reset}"); - break; - case FOSSIL_IO_PARSER_INT: - fossil_io_printf("{cyan}{reset}"); - break; - case FOSSIL_IO_PARSER_UINT: - fossil_io_printf("{cyan}{reset}"); - break; - case FOSSIL_IO_PARSER_BOOL: - fossil_io_printf("{cyan}{reset}"); - break; - case FOSSIL_IO_PARSER_FLOAT: - fossil_io_printf("{cyan}{reset}"); - break; - case FOSSIL_IO_PARSER_HEX: - fossil_io_printf("{cyan}<0xHEX>{reset}"); - break; - case FOSSIL_IO_PARSER_OCT: - fossil_io_printf("{cyan}<0OCT>{reset}"); - break; - case FOSSIL_IO_PARSER_DATE: - fossil_io_printf("{cyan}{reset}"); - break; - case FOSSIL_IO_PARSER_ARRAY: - fossil_io_printf("{cyan}{reset}"); - break; - case FOSSIL_IO_PARSER_FEATURE: - fossil_io_printf("{cyan}{reset}"); - break; - default: - fossil_io_printf("{cyan}{reset}"); - break; - } - } - arg = arg->next; - } - - // Add built-in flags to the usage - fossil_io_printf("{cyan} [--dry-run] [--verbose] [--version] [--help]{reset}"); - fossil_io_printf("\n"); - return; - } - command = command->next; - } - - // If the command is not found - fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown command '%s'. Use '--help' to see available commands.{reset}\n", command_name); -} - -fossil_io_parser_palette_t *fossil_io_parser_create_palette(const char *name, const char *description) { - if (!name || !description) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Palette name and description cannot be NULL.{reset}\n"); - return NULL; - } - - fossil_io_parser_palette_t *palette = malloc(sizeof(fossil_io_parser_palette_t)); - if (!palette) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for palette.{reset}\n"); - return NULL; - } - - palette->name = _custom_strdup(name); - if (!palette->name) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for palette name.{reset}\n"); - free(palette); - return NULL; - } - - palette->description = _custom_strdup(description); - if (!palette->description) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for palette description.{reset}\n"); - if (palette->name) free(palette->name); - free(palette); - return NULL; - } - - palette->commands = NULL; - return palette; -} - -fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palette_t *palette, const char *command_name, const char *short_name, const char *description) { - if (!palette || !command_name || !description) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Palette, command name, and description cannot be NULL.{reset}\n"); - return NULL; - } - - if (strlen(command_name) == 0) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Command name cannot be empty.{reset}\n"); - return NULL; - } - - // Check for duplicate command name or short name - fossil_io_parser_command_t *current = palette->commands; - while (current) { - if (current->name && strcmp(current->name, command_name) == 0) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Command with name '%s' already exists.{reset}\n", command_name); - return NULL; - } - if (short_name && current->short_name && strcmp(current->short_name, short_name) == 0) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Command with short name '%s' already exists.{reset}\n", short_name); - return NULL; - } - current = current->next; - } - - fossil_io_parser_command_t *command = malloc(sizeof(fossil_io_parser_command_t)); - if (!command) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for command.{reset}\n"); - return NULL; - } - - // Initialize all fields to zero/NULL - command->name = NULL; - command->short_name = NULL; - command->description = NULL; - command->arguments = NULL; - command->prev = NULL; - command->next = NULL; - - command->name = _custom_strdup(command_name); - if (!command->name) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for command name.{reset}\n"); - free(command); - return NULL; - } - - if (short_name) { - command->short_name = _custom_strdup(short_name); - if (!command->short_name) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for command short name.{reset}\n"); - free(command->name); - free(command); - return NULL; - } - } - - command->description = _custom_strdup(description); - if (!command->description) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for command description.{reset}\n"); - free(command->name); - if (command->short_name) free(command->short_name); - free(command); - return NULL; - } - - command->arguments = NULL; - command->prev = NULL; - command->next = palette->commands; - if (palette->commands) { - palette->commands->prev = command; - } - palette->commands = command; - return command; -} - -fossil_io_parser_argument_t *fossil_io_parser_add_argument(fossil_io_parser_command_t *command, const char *arg_name, const char *short_name, fossil_io_parser_arg_type_t arg_type, char **combo_options, int combo_count) { - if (!command || !arg_name) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Command and argument name cannot be NULL.{reset}\n"); - return NULL; - } - - if (strlen(arg_name) == 0) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Argument name cannot be empty.{reset}\n"); - return NULL; - } - - // Check for duplicate argument name or short name - fossil_io_parser_argument_t *current = command->arguments; - while (current) { - if (current->name && strcmp(current->name, arg_name) == 0) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Argument with name '%s' already exists.{reset}\n", arg_name); - return NULL; - } - if (short_name && current->short_name && strcmp(current->short_name, short_name) == 0) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Argument with short name '%s' already exists.{reset}\n", short_name); - return NULL; - } - current = current->next; - } - - fossil_io_parser_argument_t *argument = malloc(sizeof(fossil_io_parser_argument_t)); - if (!argument) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for argument.{reset}\n"); - return NULL; - } - - // Initialize all fields to zero/NULL - argument->name = NULL; - argument->short_name = NULL; - argument->type = FOSSIL_IO_PARSER_BOOL; - argument->value = NULL; - argument->combo_options = NULL; - argument->combo_count = 0; - argument->next = NULL; - - argument->name = _custom_strdup(arg_name); - if (!argument->name) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for argument name.{reset}\n"); - free(argument); - return NULL; - } - - if (short_name) { - argument->short_name = _custom_strdup(short_name); - if (!argument->short_name) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for argument short name.{reset}\n"); - free(argument->name); - free(argument); - return NULL; - } - } - - if (arg_type < FOSSIL_IO_PARSER_BOOL || arg_type >= FOSSIL_IO_PARSER_INVALID) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Invalid argument type for '%s'.{reset}\n", arg_name); - free(argument->name); - if (argument->short_name) free(argument->short_name); - free(argument); - return NULL; - } - - argument->type = arg_type; - argument->value = NULL; - argument->combo_options = combo_options; - argument->combo_count = combo_count; - argument->next = command->arguments; - command->arguments = argument; - return argument; -} - -// Updated parse function with error checking -void fossil_io_parser_parse(fossil_io_parser_palette_t *palette, int argc, char **argv) { - if (!palette || !argv) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Invalid arguments passed to parser.{reset}\n"); - return; - } - - if (argc < 2) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}No command provided.{reset}\n"); - return; - } - - const char *command_name = NULL; - int global_flags_processed = 0; - - // Scan for global flags and commands - for (int i = 1; i < argc; i++) { - const char *arg = argv[i]; - - if (!arg) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: NULL argument encountered.{reset}\n"); - return; - } - - if (strcmp(arg, "--help") == 0) { - if (i + 1 < argc && argv[i + 1] && argv[i + 1][0] != '-') { - show_help(argv[++i], palette); // Show help for a specific command - } else { - show_help(NULL, palette); // Show general help - } - global_flags_processed = 1; - break; - } - - if (strncmp(arg, "--color=", 8) == 0) { - const char *color_value = arg + 8; - if (fossil_io_cstring_compare(color_value, "enable") == 0) { - FOSSIL_IO_COLOR_ENABLE = 1; - } else if (fossil_io_cstring_compare(color_value, "disable") == 0) { - FOSSIL_IO_COLOR_ENABLE = 0; - } else if (fossil_io_cstring_compare(color_value, "auto") == 0) { -#ifdef _WIN32 - // On Windows, assume color is supported - FOSSIL_IO_COLOR_ENABLE = 1; -#else - if (isatty(STDOUT_FILENO)) { - FOSSIL_IO_COLOR_ENABLE = 1; - } else { - FOSSIL_IO_COLOR_ENABLE = 0; - } -#endif - } else { - fprintf(stderr, "Unknown color option: %s\n", color_value); - return; - } - continue; - } - - if (strcmp(arg, "--version") == 0) { - show_version(); - global_flags_processed = 1; - break; - } - - if (strcmp(arg, "--dry-run") == 0) { - FOSSIL_CLI_TOGGLE_DRY_RUN = 1; - fossil_io_printf("{blue}Dry-run mode enabled.{reset}\n"); - continue; - } - - if (strcmp(arg, "--verbose") == 0) { - FOSSIL_CLI_TOGGLE_VERBOSE = 1; - fossil_io_printf("{blue}Verbose mode enabled.{reset}\n"); - continue; - } - - // Assume the first non-flag argument is the command - if (arg[0] != '-' && !command_name) { - command_name = arg; - } - } - - if (global_flags_processed) { - return; - } - - if (!command_name) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}No command provided. Type '--help' to see available commands.{reset}\n"); - return; - } - - // Process specific commands - fossil_io_parser_command_t *command = palette->commands; - while (command) { - if (command->name && strcmp(command->name, command_name) == 0) { - break; - } - command = command->next; - } - - if (!command) { - // Use TI-aware suggestion system - fossil_ti_reason_t ti_reason = {0}; - const char *suggestion = suggest_command_ti(command_name, palette, &ti_reason); - - if (suggestion) { - fossil_io_fprintf(FOSSIL_STDERR, - "{red}Unknown command: '%s'. Did you mean '%s'?{reset}\n" - "{yellow}[TI] Suggestion confidence: %.2f | Distance: %d | Reason: %s{reset}\n", - command_name, - suggestion, - ti_reason.confidence_score, - ti_reason.edit_distance, - ti_reason.reason ? ti_reason.reason : "No reason provided" - ); - } else { - fossil_io_fprintf(FOSSIL_STDERR, - "{red}Unknown command: '%s'. Type '--help' to see available commands.{reset}\n", - command_name - ); - } - return; - } - - // Process command arguments - for (int i = 1; i < argc; i++) { - const char *arg_value = argv[i]; - if (!arg_value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: NULL argument encountered.{reset}\n"); - return; - } - - if (arg_value[0] == '-') { - continue; // Skip flags already processed - } - - fossil_io_parser_argument_t *argument = command->arguments; - while (argument) { - if (argument->name && strcmp(argument->name, arg_value) == 0) { - switch (argument->type) { - case FOSSIL_IO_PARSER_BOOL: - argument->value = malloc(sizeof(int)); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for boolean argument.{reset}\n"); - return; - } - if (i + 1 < argc && argv[i + 1] && - (strcmp(argv[i + 1], "true") == 0 || strcmp(argv[i + 1], "yes") == 0)) { - *(int *)argument->value = 1; // Enable - i++; - } else if (i + 1 < argc && argv[i + 1] && - (strcmp(argv[i + 1], "false") == 0 || strcmp(argv[i + 1], "no") == 0)) { - *(int *)argument->value = 0; // Disable - i++; - } else { - if (i + 1 < argc && argv[i + 1]) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Invalid value for boolean argument: %s{reset}\n", argv[i + 1]); - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for boolean argument: %s{reset}\n", arg_value); - } - free(argument->value); - argument->value = NULL; - } - break; - case FOSSIL_IO_PARSER_STRING: - if (i + 1 < argc && argv[i + 1]) { - argument->value = _custom_strdup(argv[++i]); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for string argument.{reset}\n"); - return; - } - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for string argument: %s{reset}\n", arg_value); - } - break; - case FOSSIL_IO_PARSER_INT: - if (i + 1 < argc && argv[i + 1]) { - argument->value = malloc(sizeof(int)); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for integer argument.{reset}\n"); - return; - } - *(int *)argument->value = atoi(argv[++i]); - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for integer argument: %s{reset}\n", arg_value); - } - break; - case FOSSIL_IO_PARSER_UINT: - if (i + 1 < argc && argv[i + 1]) { - argument->value = malloc(sizeof(unsigned int)); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for unsigned integer argument.{reset}\n"); - return; - } - *(unsigned int *)argument->value = (unsigned int)atol(argv[++i]); - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for unsigned integer argument: %s{reset}\n", arg_value); - } - break; - case FOSSIL_IO_PARSER_FLOAT: - if (i + 1 < argc && argv[i + 1]) { - argument->value = malloc(sizeof(float)); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for float argument.{reset}\n"); - return; - } - *(float *)argument->value = (float)atof(argv[++i]); - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for float argument: %s{reset}\n", arg_value); - } - break; - case FOSSIL_IO_PARSER_HEX: - if (i + 1 < argc && argv[i + 1]) { - argument->value = malloc(sizeof(unsigned int)); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for hex argument.{reset}\n"); - return; - } - *(unsigned int *)argument->value = (unsigned int)strtol(argv[++i], NULL, 16); - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for hex argument: %s{reset}\n", arg_value); - } - break; - case FOSSIL_IO_PARSER_OCT: - if (i + 1 < argc && argv[i + 1]) { - argument->value = malloc(sizeof(unsigned int)); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for octal argument.{reset}\n"); - return; - } - *(unsigned int *)argument->value = (unsigned int)strtol(argv[++i], NULL, 8); - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for octal argument: %s{reset}\n", arg_value); - } - break; - case FOSSIL_IO_PARSER_DATE: - if (i + 1 < argc && argv[i + 1]) { - argument->value = _custom_strdup(argv[++i]); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for date argument.{reset}\n"); - return; - } - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for date argument: %s{reset}\n", arg_value); - } - break; - case FOSSIL_IO_PARSER_ARRAY: { - if (i + 1 < argc && argv[i + 1]) { - char *array_copy = _custom_strdup(argv[++i]); - if (!array_copy) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for array argument.{reset}\n"); - return; - } - char *token = strtok(array_copy, ","); - char **array_values = NULL; - int count = 0; - - while (token) { - char **temp = realloc(array_values, sizeof(char *) * (size_t)(count + 2)); // +2 for new item and NULL terminator - if (!temp) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for array values.{reset}\n"); - free(array_copy); - for (int j = 0; j < count; j++) { - if (array_values && array_values[j]) free(array_values[j]); - } - if (array_values) free(array_values); - return; - } - array_values = temp; - array_values[count] = _custom_strdup(token); - if (!array_values[count]) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for array item.{reset}\n"); - free(array_copy); - for (int j = 0; j < count; j++) { - if (array_values[j]) free(array_values[j]); - } - free(array_values); - return; - } - count++; - array_values[count] = NULL; // NULL terminate - token = strtok(NULL, ","); - } - - argument->value = (void *)array_values; - free(array_copy); - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for array argument: %s{reset}\n", arg_value); - } - break; - } - case FOSSIL_IO_PARSER_FEATURE: - if (i + 1 < argc && argv[i + 1]) { - argument->value = malloc(sizeof(int)); - if (!argument->value) { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for feature argument.{reset}\n"); - return; - } - if (strcmp(argv[i + 1], "enable") == 0) { - *(int *)argument->value = 1; // Enable - i++; - } else if (strcmp(argv[i + 1], "disable") == 0) { - *(int *)argument->value = 0; // Disable - i++; - } else if (strcmp(argv[i + 1], "auto") == 0) { - *(int *)argument->value = 2; // Auto - i++; - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Invalid value for feature argument: %s{reset}\n", argv[i + 1]); - free(argument->value); - argument->value = NULL; - } - } else { - fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for feature argument: %s{reset}\n", arg_value); - } - break; - default: - fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown argument type for: %s{reset}\n", arg_value); - break; - } - break; - } - argument = argument->next; - } - } -} - -void fossil_io_parser_free(fossil_io_parser_palette_t *palette) { - if (!palette) return; - - fossil_io_parser_command_t *command = palette->commands; - while (command) { - fossil_io_parser_command_t *next_command = command->next; - - // Free all arguments for this command - fossil_io_parser_argument_t *argument = command->arguments; - while (argument) { - fossil_io_parser_argument_t *next_argument = argument->next; - - if (argument->name) free(argument->name); - if (argument->short_name) free(argument->short_name); - - // Handle different value types - if (argument->value) { - if (argument->type == FOSSIL_IO_PARSER_ARRAY) { - // For arrays, we need to free each string in the array - char **array_values = (char **)argument->value; - if (array_values) { - for (int i = 0; array_values[i] != NULL; i++) { - free(array_values[i]); - } - free(array_values); - } - } else { - free(argument->value); - } - } - - free(argument); - argument = next_argument; - } - - if (command->name) free(command->name); - if (command->short_name) free(command->short_name); - if (command->description) free(command->description); - - free(command); - command = next_command; - } - - if (palette->name) free(palette->name); - if (palette->description) free(palette->description); - free(palette); -} From 7a281a1754f874f47042b3de193c2d90f2c7f2e2 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:18:37 -0800 Subject: [PATCH 05/21] Delete code/logic/fossil/io/parser.h --- code/logic/fossil/io/parser.h | 223 ---------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 code/logic/fossil/io/parser.h diff --git a/code/logic/fossil/io/parser.h b/code/logic/fossil/io/parser.h deleted file mode 100644 index 51da63a..0000000 --- a/code/logic/fossil/io/parser.h +++ /dev/null @@ -1,223 +0,0 @@ -/** - * ----------------------------------------------------------------------------- - * Project: Fossil Logic - * - * This file is part of the Fossil Logic project, which aims to develop - * high-performance, cross-platform applications and libraries. The code - * contained herein is licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain - * a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * Author: Michael Gene Brockus (Dreamer) - * Date: 04/05/2014 - * - * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. - * ----------------------------------------------------------------------------- - */ -#ifndef FOSSIL_IO_PARSER_H -#define FOSSIL_IO_PARSER_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// Types of command argument -typedef enum { - FOSSIL_IO_PARSER_BOOL, // Boolean (enable/disable) - FOSSIL_IO_PARSER_STRING, // String argument - FOSSIL_IO_PARSER_INT, // Integer argument - FOSSIL_IO_PARSER_UINT, // Unsigned integer argument - FOSSIL_IO_PARSER_FLOAT, // Floating-point argument - FOSSIL_IO_PARSER_HEX, // Hexadecimal argument - FOSSIL_IO_PARSER_OCT, // Octal argument - FOSSIL_IO_PARSER_DATE, // Date argument - FOSSIL_IO_PARSER_ARRAY, // Array of values - FOSSIL_IO_PARSER_FEATURE, // Feature flag - FOSSIL_IO_PARSER_INVALID // Invalid argument type -} fossil_io_parser_arg_type_t; - -// Structure to represent each argument in the command -typedef struct fossil_io_parser_argument_s { - char *name; // Argument name - char *short_name; // Short argument name (e.g., -v for --verbose) - fossil_io_parser_arg_type_t type; // Argument type - char *value; // Parsed value - char **combo_options; // Valid options for COMBO type - int combo_count; // Number of valid options - struct fossil_io_parser_argument_s *next; // Next argument in the list -} fossil_io_parser_argument_t; - -// Structure for a command -typedef struct fossil_io_parser_command_s { - char *name; // Command name - char *short_name; // Short command name - char *description; // Command description - fossil_io_parser_argument_t *arguments; // List of arguments - struct fossil_io_parser_command_s *prev; // Previous command in the list - struct fossil_io_parser_command_s *next; // Next command in the list -} fossil_io_parser_command_t; - -// Structure for the command palette -typedef struct fossil_io_parser_palette_s { - char *name; // Palette name - char *description; // Palette description - fossil_io_parser_command_t *commands; // List of commands -} fossil_io_parser_palette_t; - -// ================================================================== -// Global Variables -// ================================================================== - -extern int FOSSIL_CLI_TOGGLE_DRY_RUN; -extern int FOSSIL_CLI_TOGGLE_VERBOSE; - -extern char *FOSSIL_CLI_TOOL_NAME; -extern char *FOSSIL_CLI_TOOL_VERSION; - -// ================================================================== -// Functions -// ================================================================== - -/** - * @brief Creates a new parser palette. - * - * @param name The name of the palette. - * @param description A description of the palette. - * @return A pointer to the newly created parser palette. - */ -fossil_io_parser_palette_t *fossil_io_parser_create_palette(const char *name, const char *description); - -/** - * @brief Adds a command to the parser palette. - * - * @param palette The parser palette to which the command will be added. - * @param command_name The name of the command. - * @param short_name The short name of the command (can be NULL). - * @param description A description of the command. - * @return A pointer to the newly added command. - */ -fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palette_t *palette, const char *command_name, const char *short_name, const char *description); - -/** - * @brief Adds an argument to a command. - * - * @param command The command to which the argument will be added. - * @param arg_name The name of the argument. - * @param short_name The short name of the argument (can be NULL). - * @param arg_type The type of the argument. - * @param combo_options (Optional) Array of valid options for COMBO type. - * @param combo_count (Optional) Number of options for COMBO type. - * @return A pointer to the newly added argument. - */ -fossil_io_parser_argument_t *fossil_io_parser_add_argument(fossil_io_parser_command_t *command, const char *arg_name, const char *short_name, fossil_io_parser_arg_type_t arg_type, char **combo_options, int combo_count); - -/** - * @brief Parses the command-line arguments using the parser palette. - * - * @param palette The parser palette to use for parsing. - * @param argc The number of command-line arguments. - * @param argv The command-line arguments. - */ -void fossil_io_parser_parse(fossil_io_parser_palette_t *palette, int argc, char **argv); - -/** - * @brief Frees the memory allocated for the parser palette. - * - * @param palette The parser palette to be freed. - */ -void fossil_io_parser_free(fossil_io_parser_palette_t *palette); - -#ifdef __cplusplus -} -#include - -/** - * C++ wrapper for the Parser API. - */ -namespace fossil { - - /** - * Namespace for I/O operations. - */ - namespace io { - /** - * Parser API for sanitizing strings. - */ - class Parser { - public: - /** - * Creates a new parser palette. - * - * @param name The name of the palette. - * @param description A description of the palette. - * @return A pointer to the newly created parser palette. - */ - static fossil_io_parser_palette_t *create_palette(const char *name, const char *description) { - return fossil_io_parser_create_palette(name, description); - } - - /** - * Adds a command to the parser palette. - * - * @param palette The parser palette to which the command will be added. - * @param command_name The name of the command. - * @param short_name The short name of the command (can be NULL). - * @param description A description of the command. - * @return A pointer to the newly added command. - */ - static fossil_io_parser_command_t *add_command(fossil_io_parser_palette_t *palette, const std::string& command_name, const std::string& short_name, const std::string& description) { - return fossil_io_parser_add_command(palette, command_name.c_str(), short_name.empty() ? nullptr : short_name.c_str(), description.c_str()); - } - - /** - * Adds an argument to a command. - * - * @param command The command to which the argument will be added. - * @param arg_name The name of the argument. - * @param short_name The short name of the argument (can be NULL). - * @param arg_type The type of the argument. - * @param combo_options (Optional) Array of valid options for COMBO type. - * @param combo_count (Optional) Number of options for COMBO type. - * @return A pointer to the newly added argument. - */ - static fossil_io_parser_argument_t *add_argument(fossil_io_parser_command_t *command, const std::string& arg_name, const std::string& short_name, fossil_io_parser_arg_type_t arg_type, char **combo_options, int combo_count) { - return fossil_io_parser_add_argument(command, arg_name.c_str(), short_name.empty() ? nullptr : short_name.c_str(), arg_type, combo_options, combo_count); - } - - /** - * Parses the command-line arguments using the parser palette. - * - * @param palette The parser palette to use for parsing. - * @param argc The number of command-line arguments. - * @param argv The command-line arguments. - */ - static void parse(fossil_io_parser_palette_t *palette, int argc, char **argv) { - fossil_io_parser_parse(palette, argc, argv); - } - - /** - * Frees the memory allocated for the parser palette. - * - * @param palette The parser palette to be freed. - */ - static void free(fossil_io_parser_palette_t *palette) { - fossil_io_parser_free(palette); - } - - }; - } -} - -#endif - -#endif /* FOSSIL_IO_FRAMEWORK_H */ From 838b56c2f1eb786ff1ac69d1851c618a74555907 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:19:06 -0800 Subject: [PATCH 06/21] Replace parser.h include with dir.h --- code/logic/fossil/io/framework.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/logic/fossil/io/framework.h b/code/logic/fossil/io/framework.h index 98e6429..39f5574 100644 --- a/code/logic/fossil/io/framework.h +++ b/code/logic/fossil/io/framework.h @@ -33,7 +33,7 @@ #include "cstring.h" #include "stream.h" #include "soap.h" -#include "parser.h" +#include "dir.h" enum { FOSSIL_IO_SUCCESS = 0, From d0d5fbb45ce3c070adc7a505498ecd012fce88b0 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:19:56 -0800 Subject: [PATCH 07/21] Delete code/tests/cases/test_parser.c --- code/tests/cases/test_parser.c | 752 --------------------------------- 1 file changed, 752 deletions(-) delete mode 100644 code/tests/cases/test_parser.c diff --git a/code/tests/cases/test_parser.c b/code/tests/cases/test_parser.c deleted file mode 100644 index 2769725..0000000 --- a/code/tests/cases/test_parser.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * ----------------------------------------------------------------------------- - * Project: Fossil Logic - * - * This file is part of the Fossil Logic project, which aims to develop high- - * performance, cross-platform applications and libraries. The code contained - * herein is subject to the terms and conditions defined in the project license. - * - * Author: Michael Gene Brockus (Dreamer) - * Date: 07/01/2024 - * - * Copyright (C) 2024 Fossil Logic. All rights reserved. - * ----------------------------------------------------------------------------- - */ -#include -#include -#include - - -// * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test Utilites -// * * * * * * * * * * * * * * * * * * * * * * * * -// Setup steps for things like test fixtures and -// mock objects are set here. -// * * * * * * * * * * * * * * * * * * * * * * * * - -// Define the test suite and add test cases -FOSSIL_SUITE(c_parser_suite); - -// Setup function for the test suite -FOSSIL_SETUP(c_parser_suite) { - // Setup code here -} - -// Teardown function for the test suite -FOSSIL_TEARDOWN(c_parser_suite) { - // Teardown code here -} - -// * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test Cases -// * * * * * * * * * * * * * * * * * * * * * * * * -// The test cases below are provided as samples, inspired -// by the Meson build system's approach of using test cases -// as samples for library usage. -// * * * * * * * * * * * * * * * * * * * * * * * * - -FOSSIL_TEST(c_create_palette) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - FOSSIL_TEST_ASSUME(strcmp(palette->name, "test_palette") == 0, "Palette name should be 'test_palette'"); - FOSSIL_TEST_ASSUME(strcmp(palette->description, "Test Description") == 0, "Palette description should be 'Test Description'"); - FOSSIL_TEST_ASSUME(palette->commands == NULL, "Palette commands should be NULL"); - fossil_io_parser_free(palette); - palette = NULL; -} // end case - -FOSSIL_TEST(c_add_command) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - FOSSIL_TEST_ASSUME(strcmp(command->name, "test_command") == 0, "Command name should be 'test_command'"); - FOSSIL_TEST_ASSUME(strcmp(command->description, "Test Command Description") == 0, "Command description should be 'Test Command Description'"); - FOSSIL_TEST_ASSUME(command->arguments == NULL, "Command arguments should be NULL"); - FOSSIL_TEST_ASSUME(palette->commands == command, "Palette commands should include the new command"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_add_argument) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "test_arg", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - FOSSIL_TEST_ASSUME(strcmp(argument->name, "test_arg") == 0, "Argument name should be 'test_arg'"); - FOSSIL_TEST_ASSUME(argument->type == FOSSIL_IO_PARSER_STRING, "Argument type should be STRING"); - FOSSIL_TEST_ASSUME(argument->value == NULL, "Argument value should be NULL"); - FOSSIL_TEST_ASSUME(command->arguments == argument, "Command arguments should include the new argument"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_command) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "test_arg", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "test_arg", "test_value"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Argument value should be set"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_free_palette) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_free(palette); - // Test passes if no crash occurs during free - FOSSIL_TEST_ASSUME(1, "Free operation completed without crash"); -} // end case - -FOSSIL_TEST(c_argument_types) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - - // Test BOOL argument - fossil_io_parser_argument_t *bool_arg = fossil_io_parser_add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(bool_arg != NULL, "BOOL argument should be added"); - FOSSIL_TEST_ASSUME(bool_arg->type == FOSSIL_IO_PARSER_BOOL, "BOOL argument type should be correct"); - - // Test STRING argument - fossil_io_parser_argument_t *string_arg = fossil_io_parser_add_argument(command, "string_arg", "sa", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(string_arg != NULL, "STRING argument should be added"); - FOSSIL_TEST_ASSUME(string_arg->type == FOSSIL_IO_PARSER_STRING, "STRING argument type should be correct"); - - // Test INT argument - fossil_io_parser_argument_t *int_arg = fossil_io_parser_add_argument(command, "int_arg", "ia", FOSSIL_IO_PARSER_INT, NULL, 0); - FOSSIL_TEST_ASSUME(int_arg != NULL, "INT argument should be added"); - FOSSIL_TEST_ASSUME(int_arg->type == FOSSIL_IO_PARSER_INT, "INT argument type should be correct"); - - // Test FLOAT argument - fossil_io_parser_argument_t *float_arg = fossil_io_parser_add_argument(command, "float_arg", "fa", FOSSIL_IO_PARSER_FLOAT, NULL, 0); - FOSSIL_TEST_ASSUME(float_arg != NULL, "FLOAT argument should be added"); - FOSSIL_TEST_ASSUME(float_arg->type == FOSSIL_IO_PARSER_FLOAT, "FLOAT argument type should be correct"); - - // Test DATE argument - fossil_io_parser_argument_t *date_arg = fossil_io_parser_add_argument(command, "date_arg", "da", FOSSIL_IO_PARSER_DATE, NULL, 0); - FOSSIL_TEST_ASSUME(date_arg != NULL, "DATE argument should be added"); - FOSSIL_TEST_ASSUME(date_arg->type == FOSSIL_IO_PARSER_DATE, "DATE argument type should be correct"); - - // Test ARRAY argument - fossil_io_parser_argument_t *array_arg = fossil_io_parser_add_argument(command, "array_arg", "aa", FOSSIL_IO_PARSER_ARRAY, NULL, 0); - FOSSIL_TEST_ASSUME(array_arg != NULL, "ARRAY argument should be added"); - FOSSIL_TEST_ASSUME(array_arg->type == FOSSIL_IO_PARSER_ARRAY, "ARRAY argument type should be correct"); - - // Test FEATURE argument - fossil_io_parser_argument_t *feature_arg = fossil_io_parser_add_argument(command, "feature_arg", "fea", FOSSIL_IO_PARSER_FEATURE, NULL, 0); - FOSSIL_TEST_ASSUME(feature_arg != NULL, "FEATURE argument should be added"); - FOSSIL_TEST_ASSUME(feature_arg->type == FOSSIL_IO_PARSER_FEATURE, "FEATURE argument type should be correct"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_null_palette) { - fossil_io_parser_palette_t *palette = NULL; - FOSSIL_TEST_ASSUME(fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description") == NULL, "Adding command to NULL palette should return NULL"); - fossil_io_parser_parse(palette, 0, NULL); - FOSSIL_TEST_ASSUME(1, "Parse with NULL palette completed without crash"); -} // end case - -FOSSIL_TEST(c_empty_command_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "", "e", "Empty Command Name Description"); - FOSSIL_TEST_ASSUME(command == NULL, "Command with empty name should not be added"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_duplicate_command_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *first_command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(first_command != NULL, "First command should be added"); - fossil_io_parser_command_t *duplicate = fossil_io_parser_add_command(palette, "test_command", "tc2", "Duplicate Command Description"); - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate command name should not be allowed"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_null_argument_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, NULL, "na", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument == NULL, "Argument with NULL name should not be added"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_invalid_argument_type) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "invalid_arg", "iv", FOSSIL_IO_PARSER_INVALID, NULL, 0); - FOSSIL_TEST_ASSUME(argument == NULL, "Argument with invalid type should not be added"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_create_palette_null_inputs) { - fossil_io_parser_palette_t *palette1 = fossil_io_parser_create_palette(NULL, "Test Description"); - FOSSIL_TEST_ASSUME(palette1 == NULL, "Palette should not be created with NULL name"); - - fossil_io_parser_palette_t *palette2 = fossil_io_parser_create_palette("test_palette", NULL); - FOSSIL_TEST_ASSUME(palette2 == NULL, "Palette should not be created with NULL description"); - - fossil_io_parser_palette_t *palette3 = fossil_io_parser_create_palette(NULL, NULL); - FOSSIL_TEST_ASSUME(palette3 == NULL, "Palette should not be created with NULL name and description"); -} // end case - -FOSSIL_TEST(c_add_command_null_inputs) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - - fossil_io_parser_command_t *command1 = fossil_io_parser_add_command(palette, NULL, "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command1 == NULL, "Command should not be added with NULL name"); - - fossil_io_parser_command_t *command2 = fossil_io_parser_add_command(palette, "test_command", "tc", NULL); - FOSSIL_TEST_ASSUME(command2 == NULL, "Command should not be added with NULL description"); - - fossil_io_parser_command_t *command3 = fossil_io_parser_add_command(NULL, "test_command", "tc", "Test Description"); - FOSSIL_TEST_ASSUME(command3 == NULL, "Command should not be added to NULL palette"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_add_command_with_short_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - FOSSIL_TEST_ASSUME(strcmp(command->short_name, "tc") == 0, "Command short name should be 'tc'"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_duplicate_command_short_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *first_command = fossil_io_parser_add_command(palette, "test_command1", "tc", "Test Command Description 1"); - FOSSIL_TEST_ASSUME(first_command != NULL, "First command should be added"); - fossil_io_parser_command_t *duplicate = fossil_io_parser_add_command(palette, "test_command2", "tc", "Test Command Description 2"); - - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate command short name should not be allowed"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_add_argument_null_command) { - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(NULL, "test_arg", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument == NULL, "Argument should not be added to NULL command"); -} // end case - -FOSSIL_TEST(c_add_argument_empty_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "", "ea", FOSSIL_IO_PARSER_STRING, NULL, 0); - - FOSSIL_TEST_ASSUME(argument == NULL, "Argument with empty name should not be added"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_duplicate_argument_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *first_arg = fossil_io_parser_add_argument(command, "test_arg", "ta1", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(first_arg != NULL, "First argument should be added"); - fossil_io_parser_argument_t *duplicate = fossil_io_parser_add_argument(command, "test_arg", "ta2", FOSSIL_IO_PARSER_INT, NULL, 0); - - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate argument name should not be allowed"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_duplicate_argument_short_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *first_arg = fossil_io_parser_add_argument(command, "test_arg1", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(first_arg != NULL, "First argument should be added"); - fossil_io_parser_argument_t *duplicate = fossil_io_parser_add_argument(command, "test_arg2", "ta", FOSSIL_IO_PARSER_INT, NULL, 0); - - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate argument short name should not be allowed"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_null_palette) { - char *argv[] = {"program", "test_command"}; - fossil_io_parser_parse(NULL, 2, argv); - FOSSIL_TEST_ASSUME(1, "Parse with NULL palette completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_null_argv) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_parse(palette, 2, NULL); - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Parse with NULL argv completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_zero_argc) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - char *argv[] = {"program"}; - fossil_io_parser_parse(palette, 1, argv); - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Parse with zero argc completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_help_flag) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - - char *argv[] = {"program", "--help"}; - fossil_io_parser_parse(palette, 2, argv); - - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Help flag parsing completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_version_flag) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - - char *argv[] = {"program", "--version"}; - fossil_io_parser_parse(palette, 2, argv); - - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Version flag parsing completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_dry_run_flag) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - - char *argv[] = {"program", "--dry-run", "test_command"}; - fossil_io_parser_parse(palette, 3, argv); - - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_DRY_RUN == 1, "Dry-run flag should be set"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_verbose_flag) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - - char *argv[] = {"program", "--verbose", "test_command"}; - fossil_io_parser_parse(palette, 3, argv); - - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_VERBOSE == 1, "Verbose flag should be set"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_unknown_command) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "valid_command", "vc", "Valid Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Valid command should be added"); - - char *argv[] = {"program", "unknown_command"}; - fossil_io_parser_parse(palette, 2, argv); - - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Unknown command parsing completed without crash"); -} // end case - -FOSSIL_TEST(c_argument_with_combo_options) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - - char *combo_options[] = {"option1", "option2", "option3"}; - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "combo_arg", "ca", FOSSIL_IO_PARSER_STRING, combo_options, 3); - - FOSSIL_TEST_ASSUME(argument != NULL, "Argument with combo options should be added"); - FOSSIL_TEST_ASSUME(argument->combo_options == combo_options, "Combo options should be set correctly"); - FOSSIL_TEST_ASSUME(argument->combo_count == 3, "Combo count should be 3"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_free_null_palette) { - fossil_io_parser_free(NULL); - FOSSIL_TEST_ASSUME(1, "Free NULL palette completed without crash"); -} // end case - -FOSSIL_TEST(c_multiple_commands_in_palette) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - - fossil_io_parser_command_t *command1 = fossil_io_parser_add_command(palette, "command1", "c1", "First Command"); - fossil_io_parser_command_t *command2 = fossil_io_parser_add_command(palette, "command2", "c2", "Second Command"); - fossil_io_parser_command_t *command3 = fossil_io_parser_add_command(palette, "command3", "c3", "Third Command"); - - FOSSIL_TEST_ASSUME(command1 != NULL, "First command should be added"); - FOSSIL_TEST_ASSUME(command2 != NULL, "Second command should be added"); - FOSSIL_TEST_ASSUME(command3 != NULL, "Third command should be added"); - - // Verify the linked list structure - FOSSIL_TEST_ASSUME(palette->commands == command3, "Latest command should be at the head"); - FOSSIL_TEST_ASSUME(command3->next == command2, "Command3 should point to command2"); - FOSSIL_TEST_ASSUME(command2->next == command1, "Command2 should point to command1"); - FOSSIL_TEST_ASSUME(command1->next == NULL, "Command1 should be the last"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_bool_argument_true) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "bool_arg", "true"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Boolean argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 1, "Boolean argument should be true"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_bool_argument_false) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "bool_arg", "false"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Boolean argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 0, "Boolean argument should be false"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_int_argument) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "int_arg", "ia", FOSSIL_IO_PARSER_INT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "int_arg", "42"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Integer argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 42, "Integer argument should be 42"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_uint_argument) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "uint_arg", "ua", FOSSIL_IO_PARSER_UINT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "uint_arg", "100"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Unsigned integer argument value should be set"); - FOSSIL_TEST_ASSUME(*(unsigned int*)command->arguments->value == 100, "Unsigned integer argument should be 100"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_float_argument) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "float_arg", "fa", FOSSIL_IO_PARSER_FLOAT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "float_arg", "3.14"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Float argument value should be set"); - FOSSIL_TEST_ASSUME(fabs(*(float*)command->arguments->value - 3.14f) < 0.001f, "Float argument should be approximately 3.14"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_hex_argument) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "hex_arg", "ha", FOSSIL_IO_PARSER_HEX, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "hex_arg", "0xFF"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Hex argument value should be set"); - FOSSIL_TEST_ASSUME(*(unsigned int*)command->arguments->value == 255, "Hex argument should be 255 (0xFF)"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_oct_argument) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "oct_arg", "oa", FOSSIL_IO_PARSER_OCT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "oct_arg", "0777"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Octal argument value should be set"); - FOSSIL_TEST_ASSUME(*(unsigned int*)command->arguments->value == 511, "Octal argument should be 511 (0777)"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_help_with_specific_command) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - - char *argv[] = {"program", "--help", "test_command"}; - fossil_io_parser_parse(palette, 3, argv); - - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Help with specific command parsing completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_color_enable) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - - char *argv[] = {"program", "color=enable"}; - fossil_io_parser_parse(palette, 2, argv); - - FOSSIL_TEST_ASSUME(FOSSIL_IO_COLOR_ENABLE == 1, "Color should be enabled"); - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_color_disable) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - - char *argv[] = {"program", "color=disable"}; - fossil_io_parser_parse(palette, 2, argv); - FOSSIL_IO_COLOR_ENABLE = 0; // Reset to default for test consistency - - FOSSIL_TEST_ASSUME(FOSSIL_IO_COLOR_ENABLE == 0, "Color should be disabled"); - - FOSSIL_IO_COLOR_ENABLE = 1; // Reset to default for other tests - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_command_with_null_short_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", NULL, "Test Command Description"); - - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added with NULL short name"); - FOSSIL_TEST_ASSUME(command->short_name == NULL, "Command short name should be NULL"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_argument_with_null_short_name) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "test_arg", NULL, FOSSIL_IO_PARSER_STRING, NULL, 0); - - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added with NULL short name"); - FOSSIL_TEST_ASSUME(argument->short_name == NULL, "Argument short name should be NULL"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_multiple_arguments_per_command) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - - fossil_io_parser_argument_t *arg1 = fossil_io_parser_add_argument(command, "arg1", "a1", FOSSIL_IO_PARSER_STRING, NULL, 0); - fossil_io_parser_argument_t *arg2 = fossil_io_parser_add_argument(command, "arg2", "a2", FOSSIL_IO_PARSER_INT, NULL, 0); - fossil_io_parser_argument_t *arg3 = fossil_io_parser_add_argument(command, "arg3", "a3", FOSSIL_IO_PARSER_BOOL, NULL, 0); - - FOSSIL_TEST_ASSUME(arg1 != NULL, "First argument should be added"); - FOSSIL_TEST_ASSUME(arg2 != NULL, "Second argument should be added"); - FOSSIL_TEST_ASSUME(arg3 != NULL, "Third argument should be added"); - - // Verify linked list structure - FOSSIL_TEST_ASSUME(command->arguments == arg3, "Latest argument should be at the head"); - FOSSIL_TEST_ASSUME(arg3->next == arg2, "Arg3 should point to arg2"); - FOSSIL_TEST_ASSUME(arg2->next == arg1, "Arg2 should point to arg1"); - FOSSIL_TEST_ASSUME(arg1->next == NULL, "Arg1 should be the last"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_missing_bool_value) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "bool_arg"}; - fossil_io_parser_parse(palette, 3, argv); - - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Parse with missing bool value completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_missing_string_value) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "string_arg", "sa", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "string_arg"}; - fossil_io_parser_parse(palette, 3, argv); - - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Parse with missing string value completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_missing_int_value) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "int_arg", "ia", FOSSIL_IO_PARSER_INT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "int_arg"}; - fossil_io_parser_parse(palette, 3, argv); - - fossil_io_parser_free(palette); - FOSSIL_TEST_ASSUME(1, "Parse with missing int value completed without crash"); -} // end case - -FOSSIL_TEST(c_parse_bool_yes_no) { - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - - char *argv[] = {"program", "test_command", "bool_arg", "yes"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Boolean argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 1, "Boolean argument should be true for 'yes'"); - - fossil_io_parser_free(palette); -} // end case - -FOSSIL_TEST(c_parse_combined_flags) { - // Reset global flags - FOSSIL_CLI_TOGGLE_DRY_RUN = 0; - FOSSIL_CLI_TOGGLE_VERBOSE = 0; - - fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - - char *argv[] = {"program", "--dry-run", "--verbose", "test_command"}; - fossil_io_parser_parse(palette, 4, argv); - - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_DRY_RUN == 1, "Dry-run flag should be set"); - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_VERBOSE == 1, "Verbose flag should be set"); - - fossil_io_parser_free(palette); -} // end case - -// * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test Pool -// * * * * * * * * * * * * * * * * * * * * * * * * -FOSSIL_TEST_GROUP(c_parser_test_cases) { - FOSSIL_TEST_ADD(c_parser_suite, c_create_palette); - FOSSIL_TEST_ADD(c_parser_suite, c_add_command); - FOSSIL_TEST_ADD(c_parser_suite, c_add_argument); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_command); - FOSSIL_TEST_ADD(c_parser_suite, c_free_palette); - FOSSIL_TEST_ADD(c_parser_suite, c_argument_types); - FOSSIL_TEST_ADD(c_parser_suite, c_null_palette); - FOSSIL_TEST_ADD(c_parser_suite, c_empty_command_name); - FOSSIL_TEST_ADD(c_parser_suite, c_duplicate_command_name); - FOSSIL_TEST_ADD(c_parser_suite, c_null_argument_name); - FOSSIL_TEST_ADD(c_parser_suite, c_invalid_argument_type); - FOSSIL_TEST_ADD(c_parser_suite, c_create_palette_null_inputs); - FOSSIL_TEST_ADD(c_parser_suite, c_add_command_null_inputs); - FOSSIL_TEST_ADD(c_parser_suite, c_add_command_with_short_name); - FOSSIL_TEST_ADD(c_parser_suite, c_duplicate_command_short_name); - FOSSIL_TEST_ADD(c_parser_suite, c_add_argument_null_command); - FOSSIL_TEST_ADD(c_parser_suite, c_add_argument_empty_name); - FOSSIL_TEST_ADD(c_parser_suite, c_duplicate_argument_name); - FOSSIL_TEST_ADD(c_parser_suite, c_duplicate_argument_short_name); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_null_palette); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_null_argv); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_zero_argc); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_help_flag); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_version_flag); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_dry_run_flag); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_verbose_flag); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_unknown_command); - FOSSIL_TEST_ADD(c_parser_suite, c_argument_with_combo_options); - FOSSIL_TEST_ADD(c_parser_suite, c_free_null_palette); - FOSSIL_TEST_ADD(c_parser_suite, c_multiple_commands_in_palette); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_bool_argument_true); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_bool_argument_false); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_int_argument); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_uint_argument); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_float_argument); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_hex_argument); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_oct_argument); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_help_with_specific_command); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_color_enable); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_color_disable); - FOSSIL_TEST_ADD(c_parser_suite, c_command_with_null_short_name); - FOSSIL_TEST_ADD(c_parser_suite, c_argument_with_null_short_name); - FOSSIL_TEST_ADD(c_parser_suite, c_multiple_arguments_per_command); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_missing_bool_value); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_missing_string_value); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_missing_int_value); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_bool_yes_no); - FOSSIL_TEST_ADD(c_parser_suite, c_parse_combined_flags); - - FOSSIL_TEST_REGISTER(c_parser_suite); -} // end of group From 375cc0a6dcb68f0a80cf10a0854d55a4fc5410f5 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:20:08 -0800 Subject: [PATCH 08/21] Delete code/tests/cases/test_parser.cpp --- code/tests/cases/test_parser.cpp | 768 ------------------------------- 1 file changed, 768 deletions(-) delete mode 100644 code/tests/cases/test_parser.cpp diff --git a/code/tests/cases/test_parser.cpp b/code/tests/cases/test_parser.cpp deleted file mode 100644 index 383685b..0000000 --- a/code/tests/cases/test_parser.cpp +++ /dev/null @@ -1,768 +0,0 @@ -/* - * ----------------------------------------------------------------------------- - * Project: Fossil Logic - * - * This file is part of the Fossil Logic project, which aims to develop high- - * performance, cross-platform applications and libraries. The code contained - * herein is subject to the terms and conditions defined in the project license. - * - * Author: Michael Gene Brockus (Dreamer) - * Date: 07/01/2024 - * - * Copyright (C) 2024 Fossil Logic. All rights reserved. - * ----------------------------------------------------------------------------- - */ -#include -#include - - -// * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test Utilites -// * * * * * * * * * * * * * * * * * * * * * * * * -// Setup steps for things like test fixtures and -// mock objects are set here. -// * * * * * * * * * * * * * * * * * * * * * * * * - -// Define the test suite and add test cases -FOSSIL_SUITE(cpp_parser_suite); - -// Setup function for the test suite -FOSSIL_SETUP(cpp_parser_suite) { - // Setup code here -} - -// Teardown function for the test suite -FOSSIL_TEARDOWN(cpp_parser_suite) { - // Teardown code here -} - -// * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test Cases -// * * * * * * * * * * * * * * * * * * * * * * * * -// The test cases below are provided as samples, inspired -// by the Meson build system's approach of using test cases -// as samples for library usage. -// * * * * * * * * * * * * * * * * * * * * * * * * - -FOSSIL_TEST(cpp_create_palette) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created"); - FOSSIL_TEST_ASSUME(strcmp(palette->name, "test_palette") == 0, "Palette name should be 'test_palette'"); - FOSSIL_TEST_ASSUME(strcmp(palette->description, "Test Description") == 0, "Palette description should be 'Test Description'"); - FOSSIL_TEST_ASSUME(palette->commands == NULL, "Palette commands should be NULL"); - parser.free(palette); - palette = NULL; -} // end case - -FOSSIL_TEST(cpp_add_command) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added"); - FOSSIL_TEST_ASSUME(strcmp(command->name, "test_command") == 0, "Command name should be 'test_command'"); - FOSSIL_TEST_ASSUME(strcmp(command->description, "Test Command Description") == 0, "Command description should be 'Test Command Description'"); - FOSSIL_TEST_ASSUME(command->arguments == NULL, "Command arguments should be NULL"); - FOSSIL_TEST_ASSUME(palette->commands == command, "Palette commands should include the new command"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_add_argument) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "test_arg", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added"); - FOSSIL_TEST_ASSUME(strcmp(argument->name, "test_arg") == 0, "Argument name should be 'test_arg'"); - FOSSIL_TEST_ASSUME(argument->type == FOSSIL_IO_PARSER_STRING, "Argument type should be STRING"); - FOSSIL_TEST_ASSUME(argument->value == NULL, "Argument value should be NULL"); - FOSSIL_TEST_ASSUME(command->arguments == argument, "Command arguments should include the new argument"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_command) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "test_arg", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "test_arg", "test_value"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Argument value should be set"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_free_palette) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - parser.free(palette); - FOSSIL_TEST_ASSUME(true, "Free operation completed without crashing"); -} // end case - -FOSSIL_TEST(cpp_argument_types) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - - // Test BOOL argument - fossil_io_parser_argument_t *bool_arg = parser.add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(bool_arg != NULL, "BOOL argument should be added"); - FOSSIL_TEST_ASSUME(bool_arg->type == FOSSIL_IO_PARSER_BOOL, "BOOL argument type should be correct"); - - // Test STRING argument - fossil_io_parser_argument_t *string_arg = parser.add_argument(command, "string_arg", "sa", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(string_arg != NULL, "STRING argument should be added"); - FOSSIL_TEST_ASSUME(string_arg->type == FOSSIL_IO_PARSER_STRING, "STRING argument type should be correct"); - - // Test INT argument - fossil_io_parser_argument_t *int_arg = parser.add_argument(command, "int_arg", "ia", FOSSIL_IO_PARSER_INT, NULL, 0); - FOSSIL_TEST_ASSUME(int_arg != NULL, "INT argument should be added"); - FOSSIL_TEST_ASSUME(int_arg->type == FOSSIL_IO_PARSER_INT, "INT argument type should be correct"); - - // Test FLOAT argument - fossil_io_parser_argument_t *float_arg = parser.add_argument(command, "float_arg", "fa", FOSSIL_IO_PARSER_FLOAT, NULL, 0); - FOSSIL_TEST_ASSUME(float_arg != NULL, "FLOAT argument should be added"); - FOSSIL_TEST_ASSUME(float_arg->type == FOSSIL_IO_PARSER_FLOAT, "FLOAT argument type should be correct"); - - // Test DATE argument - fossil_io_parser_argument_t *date_arg = parser.add_argument(command, "date_arg", "da", FOSSIL_IO_PARSER_DATE, NULL, 0); - FOSSIL_TEST_ASSUME(date_arg != NULL, "DATE argument should be added"); - FOSSIL_TEST_ASSUME(date_arg->type == FOSSIL_IO_PARSER_DATE, "DATE argument type should be correct"); - - // Test ARRAY argument - fossil_io_parser_argument_t *array_arg = parser.add_argument(command, "array_arg", "aa", FOSSIL_IO_PARSER_ARRAY, NULL, 0); - FOSSIL_TEST_ASSUME(array_arg != NULL, "ARRAY argument should be added"); - FOSSIL_TEST_ASSUME(array_arg->type == FOSSIL_IO_PARSER_ARRAY, "ARRAY argument type should be correct"); - - // Test FEATURE argument - fossil_io_parser_argument_t *feature_arg = parser.add_argument(command, "feature_arg", "fea", FOSSIL_IO_PARSER_FEATURE, NULL, 0); - FOSSIL_TEST_ASSUME(feature_arg != NULL, "FEATURE argument should be added"); - FOSSIL_TEST_ASSUME(feature_arg->type == FOSSIL_IO_PARSER_FEATURE, "FEATURE argument type should be correct"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_null_palette) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = NULL; - FOSSIL_TEST_ASSUME(parser.add_command(palette, "test_command", "tc", "Test Command Description") == NULL, "Adding command to NULL palette should return NULL"); - parser.parse(palette, 0, NULL); - FOSSIL_TEST_ASSUME(true, "Parse with NULL palette completed without crashing"); -} // end case - -FOSSIL_TEST(cpp_empty_command_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "", "e", "Empty Command Name Description"); - FOSSIL_TEST_ASSUME(command == NULL, "Command with empty name should not be added"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_duplicate_command_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *first_command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(first_command != NULL, "First command should be added successfully"); - fossil_io_parser_command_t *duplicate = parser.add_command(palette, "test_command", "tc2", "Duplicate Command Description"); - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate command name should not be allowed"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_null_argument_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "", "na", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument == NULL, "Argument with empty name should not be added"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_create_palette_null_inputs) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette1 = parser.create_palette(NULL, "Test Description"); - FOSSIL_TEST_ASSUME(palette1 == NULL, "Palette should not be created with NULL name"); - - fossil_io_parser_palette_t *palette2 = parser.create_palette("test_palette", NULL); - FOSSIL_TEST_ASSUME(palette2 == NULL, "Palette should not be created with NULL description"); - - fossil_io_parser_palette_t *palette3 = parser.create_palette(NULL, NULL); - FOSSIL_TEST_ASSUME(palette3 == NULL, "Palette should not be created with NULL name and description"); -} // end case - -FOSSIL_TEST(cpp_add_command_with_short_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - FOSSIL_TEST_ASSUME(strcmp(command->short_name, "tc") == 0, "Command short name should be 'tc'"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_duplicate_command_short_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *first_command = parser.add_command(palette, "test_command1", "tc", "Test Command Description 1"); - FOSSIL_TEST_ASSUME(first_command != NULL, "First command should be added successfully"); - fossil_io_parser_command_t *duplicate = parser.add_command(palette, "test_command2", "tc", "Test Command Description 2"); - - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate command short name should not be allowed"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_add_argument_null_command) { - fossil::io::Parser parser; - fossil_io_parser_argument_t *argument = parser.add_argument(NULL, "test_arg", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument == NULL, "Argument should not be added to NULL command"); -} // end case - -FOSSIL_TEST(cpp_add_argument_empty_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "", "ea", FOSSIL_IO_PARSER_STRING, NULL, 0); - - FOSSIL_TEST_ASSUME(argument == NULL, "Argument with empty name should not be added"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_duplicate_argument_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *first_arg = parser.add_argument(command, "test_arg", "ta1", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(first_arg != NULL, "First argument should be added successfully"); - fossil_io_parser_argument_t *duplicate = parser.add_argument(command, "test_arg", "ta2", FOSSIL_IO_PARSER_INT, NULL, 0); - - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate argument name should not be allowed"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_duplicate_argument_short_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *first_arg = parser.add_argument(command, "test_arg1", "ta", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(first_arg != NULL, "First argument should be added successfully"); - fossil_io_parser_argument_t *duplicate = parser.add_argument(command, "test_arg2", "ta", FOSSIL_IO_PARSER_INT, NULL, 0); - - FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate argument short name should not be allowed"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_null_palette) { - fossil::io::Parser parser; - const char *argv[] = {"program", "test_command"}; - parser.parse(NULL, 2, const_cast(argv)); - FOSSIL_TEST_ASSUME(true, "Parse with NULL palette completed without crashing"); -} // end case - -FOSSIL_TEST(cpp_parse_null_argv) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - parser.parse(palette, 2, NULL); - FOSSIL_TEST_ASSUME(true, "Parse with NULL argv completed without crashing"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_zero_argc) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - const char *argv[] = {"program"}; - parser.parse(palette, 1, const_cast(argv)); - FOSSIL_TEST_ASSUME(true, "Parse with zero argc handled gracefully"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_help_flag) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - - const char *argv[] = {"program", "--help"}; - parser.parse(palette, 2, const_cast(argv)); - - FOSSIL_TEST_ASSUME(true, "Help flag parsed without crashing"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_version_flag) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - - const char *argv[] = {"program", "--version"}; - parser.parse(palette, 2, const_cast(argv)); - - FOSSIL_TEST_ASSUME(true, "Version flag parsed without crashing"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_dry_run_flag) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - - const char *argv[] = {"program", "--dry-run", "test_command"}; - parser.parse(palette, 3, const_cast(argv)); - - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_DRY_RUN == 1, "Dry-run flag should be set"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_verbose_flag) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - - const char *argv[] = {"program", "--verbose", "test_command"}; - parser.parse(palette, 3, const_cast(argv)); - - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_VERBOSE == 1, "Verbose flag should be set"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_unknown_command) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "valid_command", "vc", "Valid Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Valid command should be added successfully"); - - const char *argv[] = {"program", "unknown_command"}; - parser.parse(palette, 2, const_cast(argv)); - - FOSSIL_TEST_ASSUME(true, "Unknown command handled gracefully"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_argument_with_combo_options) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - - const char *combo_options[] = {"option1", "option2", "option3"}; - fossil_io_parser_argument_t *argument = parser.add_argument(command, "combo_arg", "ca", FOSSIL_IO_PARSER_STRING, const_cast(combo_options), 3); - - FOSSIL_TEST_ASSUME(argument != NULL, "Argument with combo options should be added"); - FOSSIL_TEST_ASSUME(argument->combo_options == const_cast(combo_options), "Combo options should be set correctly"); - FOSSIL_TEST_ASSUME(argument->combo_count == 3, "Combo count should be 3"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_free_null_palette) { - fossil::io::Parser parser; - parser.free(NULL); - FOSSIL_TEST_ASSUME(true, "Free NULL palette completed without crashing"); -} // end case - -FOSSIL_TEST(cpp_multiple_commands_in_palette) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - - fossil_io_parser_command_t *command1 = parser.add_command(palette, "command1", "c1", "First Command"); - fossil_io_parser_command_t *command2 = parser.add_command(palette, "command2", "c2", "Second Command"); - fossil_io_parser_command_t *command3 = parser.add_command(palette, "command3", "c3", "Third Command"); - - FOSSIL_TEST_ASSUME(command1 != NULL, "First command should be added"); - FOSSIL_TEST_ASSUME(command2 != NULL, "Second command should be added"); - FOSSIL_TEST_ASSUME(command3 != NULL, "Third command should be added"); - - // Verify the linked list structure - FOSSIL_TEST_ASSUME(palette->commands == command3, "Latest command should be at the head"); - FOSSIL_TEST_ASSUME(command3->next == command2, "Command3 should point to command2"); - FOSSIL_TEST_ASSUME(command2->next == command1, "Command2 should point to command1"); - FOSSIL_TEST_ASSUME(command1->next == NULL, "Command1 should be the last"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_bool_argument_true) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Boolean argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "bool_arg", "true"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Boolean argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 1, "Boolean argument should be true"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_bool_argument_false) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Boolean argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "bool_arg", "false"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Boolean argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 0, "Boolean argument should be false"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_int_argument) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "int_arg", "ia", FOSSIL_IO_PARSER_INT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Integer argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "int_arg", "42"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Integer argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 42, "Integer argument should be 42"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_uint_argument) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "uint_arg", "ua", FOSSIL_IO_PARSER_UINT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Unsigned integer argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "uint_arg", "100"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Unsigned integer argument value should be set"); - FOSSIL_TEST_ASSUME(*(unsigned int*)command->arguments->value == 100, "Unsigned integer argument should be 100"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_float_argument) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "float_arg", "fa", FOSSIL_IO_PARSER_FLOAT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Float argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "float_arg", "3.14"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Float argument value should be set"); - FOSSIL_TEST_ASSUME(fabs(*(float*)command->arguments->value - 3.14f) < 0.001f, "Float argument should be approximately 3.14"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_hex_argument) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "hex_arg", "ha", FOSSIL_IO_PARSER_HEX, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Hex argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "hex_arg", "0xFF"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Hex argument value should be set"); - FOSSIL_TEST_ASSUME(*(unsigned int*)command->arguments->value == 255, "Hex argument should be 255 (0xFF)"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_oct_argument) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "oct_arg", "oa", FOSSIL_IO_PARSER_OCT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Octal argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "oct_arg", "0777"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Octal argument value should be set"); - FOSSIL_TEST_ASSUME(*(unsigned int*)command->arguments->value == 511, "Octal argument should be 511 (0777)"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_help_with_specificpp_command) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - - const char *argv[] = {"program", "--help", "test_command"}; - parser.parse(palette, 3, const_cast(argv)); - - FOSSIL_TEST_ASSUME(true, "Help with specific command parsed without crashing"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_color_enable) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - - const char *argv[] = {"program", "color=enable"}; - parser.parse(palette, 2, const_cast(argv)); - - FOSSIL_TEST_ASSUME(FOSSIL_IO_COLOR_ENABLE == 1, "Color should be enabled"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_color_disable) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - - const char *argv[] = {"program", "color=disable"}; - parser.parse(palette, 2, const_cast(argv)); - FOSSIL_IO_COLOR_ENABLE = 0; // Reset before test - - FOSSIL_TEST_ASSUME(FOSSIL_IO_COLOR_ENABLE == 0, "Color should be disabled"); - - FOSSIL_IO_COLOR_ENABLE = 1; // Reset after test - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_command_with_null_short_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "", "Test Command Description"); - - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added with empty short name"); - FOSSIL_TEST_ASSUME(command->short_name == NULL, "Command short name should be NULL"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_argument_with_null_short_name) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "test_arg", "", FOSSIL_IO_PARSER_STRING, NULL, 0); - - FOSSIL_TEST_ASSUME(argument != NULL, "Argument should be added with empty short name"); - FOSSIL_TEST_ASSUME(argument->short_name == NULL, "Argument short name should be NULL"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_multiple_arguments_per_command) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - - fossil_io_parser_argument_t *arg1 = parser.add_argument(command, "arg1", "a1", FOSSIL_IO_PARSER_STRING, NULL, 0); - fossil_io_parser_argument_t *arg2 = parser.add_argument(command, "arg2", "a2", FOSSIL_IO_PARSER_INT, NULL, 0); - fossil_io_parser_argument_t *arg3 = parser.add_argument(command, "arg3", "a3", FOSSIL_IO_PARSER_BOOL, NULL, 0); - - FOSSIL_TEST_ASSUME(arg1 != NULL, "First argument should be added"); - FOSSIL_TEST_ASSUME(arg2 != NULL, "Second argument should be added"); - FOSSIL_TEST_ASSUME(arg3 != NULL, "Third argument should be added"); - - // Verify linked list structure - FOSSIL_TEST_ASSUME(command->arguments == arg3, "Latest argument should be at the head"); - FOSSIL_TEST_ASSUME(arg3->next == arg2, "Arg3 should point to arg2"); - FOSSIL_TEST_ASSUME(arg2->next == arg1, "Arg2 should point to arg1"); - FOSSIL_TEST_ASSUME(arg1->next == NULL, "Arg1 should be the last"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_missing_bool_value) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Boolean argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "bool_arg"}; - parser.parse(palette, 3, const_cast(argv)); - - FOSSIL_TEST_ASSUME(true, "Missing boolean value handled gracefully"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_missing_string_value) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "string_arg", "sa", FOSSIL_IO_PARSER_STRING, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "String argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "string_arg"}; - parser.parse(palette, 3, const_cast(argv)); - - FOSSIL_TEST_ASSUME(true, "Missing string value handled gracefully"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_missing_int_value) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "int_arg", "ia", FOSSIL_IO_PARSER_INT, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Integer argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "int_arg"}; - parser.parse(palette, 3, const_cast(argv)); - - FOSSIL_TEST_ASSUME(true, "Missing integer value handled gracefully"); - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_bool_yes_no) { - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - fossil_io_parser_argument_t *argument = parser.add_argument(command, "bool_arg", "ba", FOSSIL_IO_PARSER_BOOL, NULL, 0); - FOSSIL_TEST_ASSUME(argument != NULL, "Boolean argument should be added successfully"); - - const char *argv[] = {"program", "test_command", "bool_arg", "yes"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(command->arguments->value != NULL, "Boolean argument value should be set"); - FOSSIL_TEST_ASSUME(*(int*)command->arguments->value == 1, "Boolean argument should be true for 'yes'"); - - parser.free(palette); -} // end case - -FOSSIL_TEST(cpp_parse_combined_flags) { - // Reset global flags - FOSSIL_CLI_TOGGLE_DRY_RUN = 0; - FOSSIL_CLI_TOGGLE_VERBOSE = 0; - - fossil::io::Parser parser; - fossil_io_parser_palette_t *palette = parser.create_palette("test_palette", "Test Description"); - FOSSIL_TEST_ASSUME(palette != NULL, "Palette should be created successfully"); - fossil_io_parser_command_t *command = parser.add_command(palette, "test_command", "tc", "Test Command Description"); - FOSSIL_TEST_ASSUME(command != NULL, "Command should be added successfully"); - - const char *argv[] = {"program", "--dry-run", "--verbose", "test_command"}; - parser.parse(palette, 4, const_cast(argv)); - - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_DRY_RUN == 1, "Dry-run flag should be set"); - FOSSIL_TEST_ASSUME(FOSSIL_CLI_TOGGLE_VERBOSE == 1, "Verbose flag should be set"); - - parser.free(palette); -} // end case - -// * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test Pool -// * * * * * * * * * * * * * * * * * * * * * * * * -FOSSIL_TEST_GROUP(cpp_parser_test_cases) { - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_create_palette); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_add_command); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_add_argument); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_command); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_free_palette); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_argument_types); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_null_palette); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_empty_command_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_duplicate_command_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_null_argument_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_create_palette_null_inputs); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_add_command_with_short_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_duplicate_command_short_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_add_argument_null_command); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_add_argument_empty_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_duplicate_argument_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_duplicate_argument_short_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_null_palette); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_null_argv); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_zero_argc); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_help_flag); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_version_flag); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_dry_run_flag); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_verbose_flag); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_unknown_command); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_argument_with_combo_options); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_free_null_palette); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_multiple_commands_in_palette); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_bool_argument_true); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_bool_argument_false); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_int_argument); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_uint_argument); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_float_argument); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_hex_argument); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_oct_argument); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_help_with_specificpp_command); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_color_enable); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_color_disable); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_command_with_null_short_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_argument_with_null_short_name); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_multiple_arguments_per_command); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_missing_bool_value); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_missing_string_value); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_missing_int_value); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_bool_yes_no); - FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_combined_flags); - - FOSSIL_TEST_REGISTER(cpp_parser_suite); -} // end of group From eb457bc3f1a4c9be39b4c432b37de474cc4822d5 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 17:09:37 -0600 Subject: [PATCH 09/21] rename fstream to io_file --- code/logic/archive.c | 20 +- code/logic/dir.c | 11 +- code/logic/{stream.c => file.c} | 96 ++++---- code/logic/fossil/io/{stream.h => file.h} | 270 +++++++++++----------- code/logic/fossil/io/input.h | 20 +- code/logic/fossil/io/output.h | 14 +- code/logic/input.c | 10 +- code/logic/output.c | 6 +- code/tests/cases/test_archive.c | 268 ++++++++++----------- code/tests/cases/test_archive.cpp | 56 ++--- code/tests/cases/test_cstring.cpp | 2 +- code/tests/cases/test_cstring.mm | 2 +- code/tests/cases/test_input.c | 18 +- code/tests/cases/test_input.cpp | 34 +-- code/tests/cases/test_input.m | 18 +- code/tests/cases/test_input.mm | 34 +-- code/tests/cases/test_stream.c | 132 +++++------ code/tests/cases/test_stream.cpp | 134 +++++------ 18 files changed, 576 insertions(+), 569 deletions(-) rename code/logic/{stream.c => file.c} (86%) rename code/logic/fossil/io/{stream.h => file.h} (78%) diff --git a/code/logic/archive.c b/code/logic/archive.c index 065af7d..1b24ad1 100644 --- a/code/logic/archive.c +++ b/code/logic/archive.c @@ -187,14 +187,14 @@ fossil_io_archive_type_t fossil_io_archive_get_type(const char *path) { } // If extension-based detection fails, try magic byte detection - fossil_fstream_t stream; - if (fossil_fstream_open(&stream, path, "rb") != 0) { + fossil_io_file_t stream; + if (fossil_io_file_open(&stream, path, "rb") != 0) { return FOSSIL_IO_ARCHIVE_UNKNOWN; } unsigned char header[512]; // Increased buffer for TAR magic at offset 257 - size_t read = fossil_fstream_read(&stream, header, 1, sizeof(header)); - fossil_fstream_close(&stream); + size_t read = fossil_io_file_read(&stream, header, 1, sizeof(header)); + fossil_io_file_close(&stream); if (read < 4) return FOSSIL_IO_ARCHIVE_UNKNOWN; @@ -455,19 +455,19 @@ bool fossil_io_archive_add_file(fossil_io_archive_t *archive, const char *src_pa if (!archive || !src_path || !archive_path) return false; if (!(archive->mode & (FOSSIL_IO_ARCHIVE_WRITE | FOSSIL_IO_ARCHIVE_APPEND))) return false; - fossil_fstream_t stream; - if (fossil_fstream_open(&stream, src_path, "rb") != 0) { + fossil_io_file_t stream; + if (fossil_io_file_open(&stream, src_path, "rb") != 0) { return false; } // Get file size - if (fossil_fstream_seek(&stream, 0, SEEK_END) != 0) { - fossil_fstream_close(&stream); + if (fossil_io_file_seek(&stream, 0, SEEK_END) != 0) { + fossil_io_file_close(&stream); return false; } - int32_t file_size = fossil_fstream_tell(&stream); - fossil_fstream_close(&stream); + int32_t file_size = fossil_io_file_tell(&stream); + fossil_io_file_close(&stream); if (file_size < 0) return false; diff --git a/code/logic/dir.c b/code/logic/dir.c index 2b2cc50..48c56c36 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -28,12 +28,16 @@ #include #include +#include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include #include + #ifndef PATH_MAX + #define PATH_MAX MAX_PATH + #endif #define PATHSEP '\\' #define PATHSEP_STR "\\" #define mkdir_native(p,mode) _mkdir(p) @@ -46,6 +50,9 @@ #include #include #include + #ifndef PATH_MAX + #define PATH_MAX 4096 + #endif #define PATHSEP '/' #define PATHSEP_STR "/" #define mkdir_native(p,mode) mkdir((p),(mode)) @@ -179,7 +186,7 @@ int32_t fossil_io_dir_create(const char *path){ if (!fossil_io_dir_exists(tmp)){ int rc; #ifdef _WIN32 - rc = mkdir_native(tmp); + rc = mkdir_native(tmp, 0); #else rc = mkdir_native(tmp, 0755); #endif @@ -195,7 +202,7 @@ int32_t fossil_io_dir_create(const char *path){ // final create if not exists if (!fossil_io_dir_exists(path)){ #ifdef _WIN32 - if (mkdir_native(path) != 0 && errno != EEXIST) return -1; + if (mkdir_native(path, 0) != 0 && errno != EEXIST) return -1; #else if (mkdir_native(path, 0755) != 0 && errno != EEXIST) return -1; #endif diff --git a/code/logic/stream.c b/code/logic/file.c similarity index 86% rename from code/logic/stream.c rename to code/logic/file.c index 9ce87cd..3cce838 100644 --- a/code/logic/stream.c +++ b/code/logic/file.c @@ -39,9 +39,9 @@ #endif #include -fossil_fstream_t *FOSSIL_STDIN; -fossil_fstream_t *FOSSIL_STDOUT; -fossil_fstream_t *FOSSIL_STDERR; +fossil_io_file_t *FOSSIL_STDIN; +fossil_io_file_t *FOSSIL_STDOUT; +fossil_io_file_t *FOSSIL_STDERR; typedef enum { FOSSIL_BUFFER_SMALL = 100, @@ -54,9 +54,9 @@ typedef enum { typedef struct { const char *keyword; const char *mode; -} fossil_fstream_mode_entry_t; +} fossil_io_file_mode_entry_t; -static const fossil_fstream_mode_entry_t fossil_fstream_mode_table[] = { +static const fossil_io_file_mode_entry_t fossil_io_file_mode_table[] = { // Classic C modes (standard fopen strings) { "r", "r" }, { "rb", "rb" }, { "w", "w" }, { "wb", "wb" }, @@ -86,18 +86,18 @@ static const fossil_fstream_mode_entry_t fossil_fstream_mode_table[] = { { NULL, NULL } }; -static const char *fossil_fstream_mode_from_keyword(const char *keyword) { +static const char *fossil_io_file_mode_from_keyword(const char *keyword) { if (keyword == NULL) return NULL; - for (int i = 0; fossil_fstream_mode_table[i].keyword != NULL; i++) { - if (strcmp(keyword, fossil_fstream_mode_table[i].keyword) == 0) { - return fossil_fstream_mode_table[i].mode; + for (int i = 0; fossil_io_file_mode_table[i].keyword != NULL; i++) { + if (strcmp(keyword, fossil_io_file_mode_table[i].keyword) == 0) { + return fossil_io_file_mode_table[i].mode; } } return NULL; } // Open a stream for file operations -int32_t fossil_fstream_open(fossil_fstream_t *stream, const char *filename, const char *mode) { +int32_t fossil_io_file_open(fossil_io_file_t *stream, const char *filename, const char *mode) { if (stream == NULL || filename == NULL || mode == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -108,7 +108,7 @@ int32_t fossil_fstream_open(fossil_fstream_t *stream, const char *filename, cons return FOSSIL_ERROR_LIMIT_REACHED; } - stream->file = fopen(filename, fossil_fstream_mode_from_keyword(mode)); + stream->file = fopen(filename, fossil_io_file_mode_from_keyword(mode)); if (stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: File not found - %s\n", filename); return FOSSIL_ERROR_FILE_NOT_FOUND; @@ -121,7 +121,7 @@ int32_t fossil_fstream_open(fossil_fstream_t *stream, const char *filename, cons } // Close an open stream -void fossil_fstream_close(fossil_fstream_t *stream) { +void fossil_io_file_close(fossil_io_file_t *stream) { if (stream != NULL && stream->file != NULL) { if (fclose(stream->file) != 0) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Failed to close file - %s\n", stream->filename); @@ -130,7 +130,7 @@ void fossil_fstream_close(fossil_fstream_t *stream) { } } -int32_t fossil_fstream_redirect_to_devnull(fossil_fstream_t *stream) { +int32_t fossil_io_file_redirect_to_devnull(fossil_io_file_t *stream) { if (!stream) { return -1; // Invalid stream } @@ -158,13 +158,13 @@ int32_t fossil_fstream_redirect_to_devnull(fossil_fstream_t *stream) { return 0; } -int32_t fossil_fstream_freopen(fossil_fstream_t *stream, const char *filename, const char *mode, FILE *file) { +int32_t fossil_io_file_freopen(fossil_io_file_t *stream, const char *filename, const char *mode, FILE *file) { if (stream == NULL || filename == NULL || mode == NULL || file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; } - FILE *new_file = freopen(filename, fossil_fstream_mode_from_keyword(mode), file); + FILE *new_file = freopen(filename, fossil_io_file_mode_from_keyword(mode), file); if (new_file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: File not found - %s\n", filename); return FOSSIL_ERROR_FILE_NOT_FOUND; @@ -180,7 +180,7 @@ int32_t fossil_fstream_freopen(fossil_fstream_t *stream, const char *filename, c } // Read data from an open stream -size_t fossil_fstream_read(fossil_fstream_t *stream, void *buffer, size_t size, size_t count) { +size_t fossil_io_file_read(fossil_io_file_t *stream, void *buffer, size_t size, size_t count) { if (stream == NULL || buffer == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -197,7 +197,7 @@ size_t fossil_fstream_read(fossil_fstream_t *stream, void *buffer, size_t size, } // Write data to an open stream -size_t fossil_fstream_write(fossil_fstream_t *stream, const void *buffer, size_t size, size_t count) { +size_t fossil_io_file_write(fossil_io_file_t *stream, const void *buffer, size_t size, size_t count) { if (stream == NULL || buffer == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -214,7 +214,7 @@ size_t fossil_fstream_write(fossil_fstream_t *stream, const void *buffer, size_t } // Append data to the end of an open stream -int32_t fossil_fstream_append(fossil_fstream_t *stream, const void * restrict buffer, size_t size, int32_t count) { +int32_t fossil_io_file_append(fossil_io_file_t *stream, const void * restrict buffer, size_t size, int32_t count) { if (stream == NULL || buffer == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -232,7 +232,7 @@ int32_t fossil_fstream_append(fossil_fstream_t *stream, const void * restrict bu } // Seek to a specified position in an open stream -int32_t fossil_fstream_seek(fossil_fstream_t *stream, int64_t offset, int32_t origin) { +int32_t fossil_io_file_seek(fossil_io_file_t *stream, int64_t offset, int32_t origin) { if (stream == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -249,7 +249,7 @@ int32_t fossil_fstream_seek(fossil_fstream_t *stream, int64_t offset, int32_t or } // Get the current position of the file pointer in an open stream -int32_t fossil_fstream_tell(fossil_fstream_t *stream) { +int32_t fossil_io_file_tell(fossil_io_file_t *stream) { if (stream == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -266,7 +266,7 @@ int32_t fossil_fstream_tell(fossil_fstream_t *stream) { } // Save an open stream to a new file -int32_t fossil_fstream_save(fossil_fstream_t *stream, const char *new_filename) { +int32_t fossil_io_file_save(fossil_io_file_t *stream, const char *new_filename) { if (stream == NULL || stream->file == NULL || new_filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -285,7 +285,7 @@ int32_t fossil_fstream_save(fossil_fstream_t *stream, const char *new_filename) } // Reopen the file with the new name - int32_t result = fossil_fstream_open(stream, new_filename, "r"); + int32_t result = fossil_io_file_open(stream, new_filename, "r"); if (result != FOSSIL_ERROR_OK) { fossil_io_fprintf(FOSSIL_STDERR, "Error: File not found - %s\n", strerror(errno)); @@ -295,7 +295,7 @@ int32_t fossil_fstream_save(fossil_fstream_t *stream, const char *new_filename) } // Copy a file from the source to the destination -int32_t fossil_fstream_copy(const char *source_filename, const char *destination_filename) { +int32_t fossil_io_file_copy(const char *source_filename, const char *destination_filename) { if (source_filename == NULL || destination_filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -333,7 +333,7 @@ int32_t fossil_fstream_copy(const char *source_filename, const char *destination return FOSSIL_ERROR_OK; } -int32_t fossil_fstream_remove(const char *filename) { +int32_t fossil_io_file_remove(const char *filename) { if (filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -352,7 +352,7 @@ int32_t fossil_fstream_remove(const char *filename) { } } -int32_t fossil_fstream_rename(const char *old_filename, const char *new_filename) { +int32_t fossil_io_file_rename(const char *old_filename, const char *new_filename) { if (old_filename == NULL || new_filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -366,7 +366,7 @@ int32_t fossil_fstream_rename(const char *old_filename, const char *new_filename return FOSSIL_ERROR_OK; } -int32_t fossil_fstream_flush(fossil_fstream_t *stream) { +int32_t fossil_io_file_flush(fossil_io_file_t *stream) { if (stream == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -380,7 +380,7 @@ int32_t fossil_fstream_flush(fossil_fstream_t *stream) { return FOSSIL_ERROR_OK; } -int32_t fossil_fstream_setpos(fossil_fstream_t *stream, int32_t pos) { +int32_t fossil_io_file_setpos(fossil_io_file_t *stream, int32_t pos) { if (stream == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -394,7 +394,7 @@ int32_t fossil_fstream_setpos(fossil_fstream_t *stream, int32_t pos) { return FOSSIL_ERROR_OK; } -int32_t fossil_fstream_getpos(fossil_fstream_t *stream, int32_t *pos) { +int32_t fossil_io_file_getpos(fossil_io_file_t *stream, int32_t *pos) { if (stream == NULL || stream->file == NULL || pos == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -409,7 +409,7 @@ int32_t fossil_fstream_getpos(fossil_fstream_t *stream, int32_t *pos) { return FOSSIL_ERROR_OK; } -int32_t fossil_fstream_rotate(const char *filename, int32_t n) { +int32_t fossil_io_file_rotate(const char *filename, int32_t n) { if (filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -426,7 +426,7 @@ int32_t fossil_fstream_rotate(const char *filename, int32_t n) { } snprintf(new_filename, FOSSIL_BUFFER_MEDIUM, "%s.%d", filename, i); - if (fossil_fstream_rename(old_filename, new_filename) != FOSSIL_ERROR_OK) { + if (fossil_io_file_rename(old_filename, new_filename) != FOSSIL_ERROR_OK) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Failed to rotate file %s\n", filename); return FOSSIL_ERROR_IO; } @@ -436,7 +436,7 @@ int32_t fossil_fstream_rotate(const char *filename, int32_t n) { } // Create a backup of a file with a specified backup suffix -int32_t fossil_fstream_backup(const char *filename, const char *backup_suffix) { +int32_t fossil_io_file_backup(const char *filename, const char *backup_suffix) { if (filename == NULL || backup_suffix == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -445,7 +445,7 @@ int32_t fossil_fstream_backup(const char *filename, const char *backup_suffix) { char backup_filename[FOSSIL_BUFFER_MEDIUM + 10]; // Length of backup_suffix + maximum integer length snprintf(backup_filename, FOSSIL_BUFFER_MEDIUM + 10, "%s%s", filename, backup_suffix); - if (fossil_fstream_copy(filename, backup_filename) != FOSSIL_ERROR_OK) { + if (fossil_io_file_copy(filename, backup_filename) != FOSSIL_ERROR_OK) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Failed to create backup for %s\n", filename); return FOSSIL_ERROR_IO; } @@ -454,7 +454,7 @@ int32_t fossil_fstream_backup(const char *filename, const char *backup_suffix) { } // Check if a file exists -int32_t fossil_fstream_file_exists(const char *filename) { +int32_t fossil_io_file_file_exists(const char *filename) { if (filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -469,7 +469,7 @@ int32_t fossil_fstream_file_exists(const char *filename) { } // Get the size of an open stream -int32_t fossil_fstream_get_size(fossil_fstream_t *stream) { +int32_t fossil_io_file_get_size(fossil_io_file_t *stream) { if (stream == NULL || stream->file == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -488,7 +488,7 @@ int32_t fossil_fstream_get_size(fossil_fstream_t *stream) { } // Delete a file -int32_t fossil_fstream_delete(const char *filename) { +int32_t fossil_io_file_delete(const char *filename) { if (filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return FOSSIL_ERROR_CNULL_POINTER; @@ -503,7 +503,7 @@ int32_t fossil_fstream_delete(const char *filename) { } // Detect file type (Regular file, Directory, Symbolic link) -int fossil_fstream_get_type(const char *filename) { +int fossil_io_file_get_type(const char *filename) { if (filename == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Null pointer\n"); return -1; @@ -538,11 +538,11 @@ int fossil_fstream_get_type(const char *filename) { #endif } -int32_t fossil_fstream_is_open(const fossil_fstream_t *stream) { +int32_t fossil_io_file_is_open(const fossil_io_file_t *stream) { return stream != NULL && stream->file != NULL; } -int32_t fossil_fstream_is_readable(const char *filename) { +int32_t fossil_io_file_is_readable(const char *filename) { #ifdef _WIN32 DWORD attrs = GetFileAttributesA(filename); return (attrs != INVALID_FILE_ATTRIBUTES && !(attrs & FILE_ATTRIBUTE_DIRECTORY)); @@ -551,15 +551,15 @@ int32_t fossil_fstream_is_readable(const char *filename) { #endif } -fossil_fstream_t fossil_fstream_tempfile(void) { - fossil_fstream_t temp_stream; +fossil_io_file_t fossil_io_file_tempfile(void) { + fossil_io_file_t temp_stream; char temp_filename[FOSSIL_BUFFER_MEDIUM] = {0}; #ifdef _WIN32 // Use GetTempFileName for Windows if (GetTempFileNameA(".", "fossil", 0, temp_filename) == 0) { fprintf(stderr, "Error: Failed to create temporary file\n"); - return (fossil_fstream_t){NULL, ""}; + return (fossil_io_file_t){NULL, ""}; } #else // Use PID + timestamp + random number for POSIX @@ -572,15 +572,15 @@ fossil_fstream_t fossil_fstream_tempfile(void) { #endif // Open the temporary file - if (fossil_fstream_open(&temp_stream, temp_filename, "wb+") != FOSSIL_ERROR_OK) { + if (fossil_io_file_open(&temp_stream, temp_filename, "wb+") != FOSSIL_ERROR_OK) { fprintf(stderr, "Error: Failed to open temporary file - %s\n", temp_filename); - return (fossil_fstream_t){NULL, ""}; + return (fossil_io_file_t){NULL, ""}; } return temp_stream; } -int32_t fossil_fstream_is_writable(const char *filename) { +int32_t fossil_io_file_is_writable(const char *filename) { #ifdef _WIN32 DWORD attrs = GetFileAttributesA(filename); if (attrs == INVALID_FILE_ATTRIBUTES || (attrs & FILE_ATTRIBUTE_DIRECTORY)) { @@ -592,7 +592,7 @@ int32_t fossil_fstream_is_writable(const char *filename) { #endif } -int32_t fossil_fstream_is_executable(const char *filename) { +int32_t fossil_io_file_is_executable(const char *filename) { #ifdef _WIN32 // On Windows, executables typically have extensions like .exe, .bat, .cmd const char *ext = strrchr(filename, '.'); @@ -602,7 +602,7 @@ int32_t fossil_fstream_is_executable(const char *filename) { #endif } -int32_t fossil_fstream_set_permissions(const char *filename, int32_t mode) { +int32_t fossil_io_file_set_permissions(const char *filename, int32_t mode) { #ifdef _WIN32 DWORD attrs = GetFileAttributesA(filename); if (attrs == INVALID_FILE_ATTRIBUTES) { @@ -621,7 +621,7 @@ int32_t fossil_fstream_set_permissions(const char *filename, int32_t mode) { #endif } -int32_t fossil_fstream_get_permissions(const char *filename, int32_t *mode) { +int32_t fossil_io_file_get_permissions(const char *filename, int32_t *mode) { if (!mode) { return -1; // Null pointer error } @@ -647,7 +647,7 @@ int32_t fossil_fstream_get_permissions(const char *filename, int32_t *mode) { #endif } -void fossil_fstream_rewind(fossil_fstream_t *stream) { +void fossil_io_file_rewind(fossil_io_file_t *stream) { if (stream && stream->file) { rewind(stream->file); } diff --git a/code/logic/fossil/io/stream.h b/code/logic/fossil/io/file.h similarity index 78% rename from code/logic/fossil/io/stream.h rename to code/logic/fossil/io/file.h index 231c998..1d6172c 100644 --- a/code/logic/fossil/io/stream.h +++ b/code/logic/fossil/io/file.h @@ -22,8 +22,8 @@ * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. * ----------------------------------------------------------------------------- */ -#ifndef FOSSIL_IO_STREAM_H -#define FOSSIL_IO_STREAM_H +#ifndef FOSSIL_IO_FILE_H +#define FOSSIL_IO_FILE_H #include #include @@ -41,11 +41,11 @@ extern "C" { typedef struct { FILE *file; // Pointer to the FILE structure for the stream char filename[500]; // Array to store the filename -} fossil_fstream_t; +} fossil_io_file_t; -extern fossil_fstream_t *FOSSIL_STDIN; -extern fossil_fstream_t *FOSSIL_STDOUT; -extern fossil_fstream_t *FOSSIL_STDERR; +extern fossil_io_file_t *FOSSIL_STDIN; +extern fossil_io_file_t *FOSSIL_STDOUT; +extern fossil_io_file_t *FOSSIL_STDERR; #define FOSSIL_STDIN (FOSSIL_STDIN) #define FOSSIL_STDOUT (FOSSIL_STDOUT) @@ -56,126 +56,126 @@ extern fossil_fstream_t *FOSSIL_STDERR; * * This function reopens a stream with a new file. * - * @param stream Pointer to the fossil_fstream_t structure to reopen. + * @param stream Pointer to the fossil_io_file_t structure to reopen. * @param filename The name of the file to reopen. * @param mode The mode in which to reopen the file. * @param file Pointer to the FILE structure to reopen. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_freopen(fossil_fstream_t *stream, const char *filename, const char *mode, FILE *file); +int32_t fossil_io_file_freopen(fossil_io_file_t *stream, const char *filename, const char *mode, FILE *file); /** * Open a stream for file operations. * * This function opens a file stream, allowing read or write operations on the specified file. * - * @param stream Pointer to the fossil_fstream_t structure to store the opened stream. + * @param stream Pointer to the fossil_io_file_t structure to store the opened stream. * @param filename The name of the file to be opened. * @param mode The mode in which to open the file (e.g., "r" for read, "w" for write). * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_open(fossil_fstream_t *stream, const char *filename, const char *mode); +int32_t fossil_io_file_open(fossil_io_file_t *stream, const char *filename, const char *mode); /** * Close an open stream. * * This function closes a previously opened stream, releasing associated resources. * - * @param stream Pointer to the fossil_fstream_t structure to be closed. + * @param stream Pointer to the fossil_io_file_t structure to be closed. */ -void fossil_fstream_close(fossil_fstream_t *stream); +void fossil_io_file_close(fossil_io_file_t *stream); /** * Redirect a stream to /dev/null. * * This function redirects the given stream to /dev/null, effectively discarding any data written to it. * - * @param stream Pointer to the fossil_fstream_t structure to redirect. + * @param stream Pointer to the fossil_io_file_t structure to redirect. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_redirect_to_devnull(fossil_fstream_t *stream); +int32_t fossil_io_file_redirect_to_devnull(fossil_io_file_t *stream); /** * Check if a stream is open. * * This function checks if a stream is open. * - * @param stream Pointer to the fossil_fstream_t structure to check. + * @param stream Pointer to the fossil_io_file_t structure to check. * @return 1 if the stream is open, 0 if not. */ -int32_t fossil_fstream_is_open(const fossil_fstream_t *stream); +int32_t fossil_io_file_is_open(const fossil_io_file_t *stream); /** * Read data from an open stream. * * This function reads data from an open stream into a buffer. * - * @param stream Pointer to the fossil_fstream_t structure from which to read. + * @param stream Pointer to the fossil_io_file_t structure from which to read. * @param buffer Pointer to the buffer to store the read data. * @param size Size of each element to be read. * @param count Number of elements to read. * @return The total number of elements successfully read. */ -size_t fossil_fstream_read(fossil_fstream_t *stream, void *buffer, size_t size, size_t count); +size_t fossil_io_file_read(fossil_io_file_t *stream, void *buffer, size_t size, size_t count); /** * Write data to an open stream. * * This function writes data from a buffer to an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to which to write. + * @param stream Pointer to the fossil_io_file_t structure to which to write. * @param buffer Pointer to the buffer containing the data to be written. * @param size Size of each element to be written. * @param count Number of elements to write. * @return The total number of elements successfully written. */ -size_t fossil_fstream_write(fossil_fstream_t *stream, const void *buffer, size_t size, size_t count); +size_t fossil_io_file_write(fossil_io_file_t *stream, const void *buffer, size_t size, size_t count); /** * Append data to the end of an open stream. * * This function appends data from a buffer to the end of an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to which to append. + * @param stream Pointer to the fossil_io_file_t structure to which to append. * @param buffer Pointer to the buffer containing the data to be appended. * @param size Size of each element to be appended. * @param count Number of elements to append. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_append(fossil_fstream_t *stream, const void *buffer, size_t size, int32_t count); +int32_t fossil_io_file_append(fossil_io_file_t *stream, const void *buffer, size_t size, int32_t count); /** * Seek to a specified position in an open stream. * * This function moves the file pointer associated with the stream to a new position. * - * @param stream Pointer to the fossil_fstream_t structure to seek. + * @param stream Pointer to the fossil_io_file_t structure to seek. * @param offset The offset from the specified origin. * @param origin The starting position for the offset (SEEK_SET, SEEK_CUR, SEEK_END). * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_seek(fossil_fstream_t *stream, int64_t offset, int32_t origin); +int32_t fossil_io_file_seek(fossil_io_file_t *stream, int64_t offset, int32_t origin); /** * Get the current position of the file pointer in an open stream. * * This function retrieves the current position of the file pointer in an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to get the position of. + * @param stream Pointer to the fossil_io_file_t structure to get the position of. * @return The current position of the file pointer. */ -int32_t fossil_fstream_tell(fossil_fstream_t *stream); +int32_t fossil_io_file_tell(fossil_io_file_t *stream); /** * Save an open stream to a new file. * * This function saves the contents of an open stream to a new file. * - * @param stream Pointer to the fossil_fstream_t structure to be saved. + * @param stream Pointer to the fossil_io_file_t structure to be saved. * @param new_filename The name of the new file to save to. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_save(fossil_fstream_t *stream, const char *new_filename); +int32_t fossil_io_file_save(fossil_io_file_t *stream, const char *new_filename); /** * Copy a file from the source to the destination. @@ -186,7 +186,7 @@ int32_t fossil_fstream_save(fossil_fstream_t *stream, const char *new_filename); * @param destination_filename The name of the destination file. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_copy(const char *source_filename, const char *destination_filename); +int32_t fossil_io_file_copy(const char *source_filename, const char *destination_filename); /** * Remove a file stream. @@ -196,7 +196,7 @@ int32_t fossil_fstream_copy(const char *source_filename, const char *destination * @param filename The name of the file to remove. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_remove(const char *filename); +int32_t fossil_io_file_remove(const char *filename); /** * Rename a file or directory. @@ -207,38 +207,38 @@ int32_t fossil_fstream_remove(const char *filename); * @param new_filename The new name to assign to the file or directory. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_rename(const char *old_filename, const char *new_filename); +int32_t fossil_io_file_rename(const char *old_filename, const char *new_filename); /** * Flush the contents of an open stream. * * This function flushes the contents of an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to flush. + * @param stream Pointer to the fossil_io_file_t structure to flush. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_flush(fossil_fstream_t *stream); +int32_t fossil_io_file_flush(fossil_io_file_t *stream); /** * Seek to the beginning of an open stream. * * This function moves the file pointer associated with the stream to the beginning. * - * @param stream Pointer to the fossil_fstream_t structure to seek. + * @param stream Pointer to the fossil_io_file_t structure to seek. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_setpos(fossil_fstream_t *stream, int32_t pos); +int32_t fossil_io_file_setpos(fossil_io_file_t *stream, int32_t pos); /** * Get the current position of the file pointer in an open stream. * * This function retrieves the current position of the file pointer in an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to get the position of. + * @param stream Pointer to the fossil_io_file_t structure to get the position of. * @param pos Pointer to store the current position of the file pointer. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_getpos(fossil_fstream_t *stream, int32_t *pos); +int32_t fossil_io_file_getpos(fossil_io_file_t *stream, int32_t *pos); /** * Rotate a file stream. @@ -249,7 +249,7 @@ int32_t fossil_fstream_getpos(fossil_fstream_t *stream, int32_t *pos); * @param n The number of rotations to perform. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_rotate(const char *filename, int32_t n); +int32_t fossil_io_file_rotate(const char *filename, int32_t n); /** * Create a backup of a file with a specified backup suffix. @@ -260,7 +260,7 @@ int32_t fossil_fstream_rotate(const char *filename, int32_t n); * @param backup_suffix The suffix to be appended to the backup file. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_backup(const char *filename, const char *backup_suffix); +int32_t fossil_io_file_backup(const char *filename, const char *backup_suffix); /** * Check if a file exists. @@ -270,17 +270,17 @@ int32_t fossil_fstream_backup(const char *filename, const char *backup_suffix); * @param filename The name of the file to check for existence. * @return 1 if the file exists, 0 if not. */ -int32_t fossil_fstream_file_exists(const char *filename); +int32_t fossil_io_file_file_exists(const char *filename); /** * Get the size of an open stream. * * This function retrieves the size of an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to get the size of. + * @param stream Pointer to the fossil_io_file_t structure to get the size of. * @return The size of the open stream. */ -int32_t fossil_fstream_get_size(fossil_fstream_t *stream); +int32_t fossil_io_file_get_size(fossil_io_file_t *stream); /** * Delete a file. @@ -290,7 +290,7 @@ int32_t fossil_fstream_get_size(fossil_fstream_t *stream); * @param filename The name of the file to be deleted. * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_delete(const char *filename); +int32_t fossil_io_file_delete(const char *filename); /** * Get the type of a file stream. @@ -300,7 +300,7 @@ int32_t fossil_fstream_delete(const char *filename); * @param filename The name of the file to get the type of. * @return The type of the file stream. */ -int fossil_fstream_get_type(const char *filename); +int fossil_io_file_get_type(const char *filename); /** * Create a temporary file. @@ -309,7 +309,7 @@ int fossil_fstream_get_type(const char *filename); * * @return A pointer to the name of the temporary file, or NULL on failure. */ -fossil_fstream_t fossil_fstream_tempfile(void); +fossil_io_file_t fossil_io_file_tempfile(void); /** * Check if a file is readable. @@ -319,7 +319,7 @@ fossil_fstream_t fossil_fstream_tempfile(void); * @param filename The name of the file to check. * @return 1 if readable, 0 otherwise. */ -int32_t fossil_fstream_is_readable(const char *filename); +int32_t fossil_io_file_is_readable(const char *filename); /** * Check if a file is writable. @@ -329,7 +329,7 @@ int32_t fossil_fstream_is_readable(const char *filename); * @param filename The name of the file to check. * @return 1 if writable, 0 otherwise. */ -int32_t fossil_fstream_is_writable(const char *filename); +int32_t fossil_io_file_is_writable(const char *filename); /** * Check if a file is executable. @@ -339,7 +339,7 @@ int32_t fossil_fstream_is_writable(const char *filename); * @param filename The name of the file to check. * @return 1 if executable, 0 otherwise. */ -int32_t fossil_fstream_is_executable(const char *filename); +int32_t fossil_io_file_is_executable(const char *filename); /** * Set file permissions. @@ -350,7 +350,7 @@ int32_t fossil_fstream_is_executable(const char *filename); * @param mode The permissions to set (POSIX: chmod-style). * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_set_permissions(const char *filename, int32_t mode); +int32_t fossil_io_file_set_permissions(const char *filename, int32_t mode); /** * Get file permissions. @@ -361,17 +361,17 @@ int32_t fossil_fstream_set_permissions(const char *filename, int32_t mode); * @param mode Pointer to store the retrieved permissions (POSIX style). * @return 0 on success, non-zero on failure. */ -int32_t fossil_fstream_get_permissions(const char *filename, int32_t *mode); +int32_t fossil_io_file_get_permissions(const char *filename, int32_t *mode); /** * @brief Rewinds the file stream to the beginning. * - * Resets the position of the file pointer in the given `fossil_fstream_t` + * Resets the position of the file pointer in the given `fossil_io_file_t` * structure to the beginning of the file, if the stream and file are valid. * - * @param stream Pointer to a `fossil_fstream_t` structure representing the file stream. + * @param stream Pointer to a `fossil_io_file_t` structure representing the file stream. */ -void fossil_fstream_rewind(fossil_fstream_t *stream); +void fossil_io_file_rewind(fossil_io_file_t *stream); #ifdef __cplusplus } @@ -397,14 +397,14 @@ namespace fossil { * * This function reopens a stream with a new file. * - * @param stream Pointer to the fossil_fstream_t structure to reopen. + * @param stream Pointer to the fossil_io_file_t structure to reopen. * @param filename The name of the file to reopen. * @param mode The mode in which to reopen the file. * @param file Pointer to the FILE structure to reopen. * @return 0 on success, non-zero on failure. */ - static int32_t freopen(fossil_fstream_t *stream, const char *filename, const char *mode, FILE *file) { - return fossil_fstream_freopen(stream, filename, mode, file); + static int32_t freopen(fossil_io_file_t *stream, const char *filename, const char *mode, FILE *file) { + return fossil_io_file_freopen(stream, filename, mode, file); } /** @@ -412,14 +412,14 @@ namespace fossil { * * This function reopens a stream with a new file. * - * @param stream Pointer to the fossil_fstream_t structure to reopen. + * @param stream Pointer to the fossil_io_file_t structure to reopen. * @param filename The name of the file to reopen. * @param mode The mode in which to reopen the file. * @param file Pointer to the FILE structure to reopen. * @return 0 on success, non-zero on failure. */ - static int32_t freopen(fossil_fstream_t *stream, const std::string &filename, const std::string &mode, FILE *file) { - return fossil_fstream_freopen(stream, filename.c_str(), mode.c_str(), file); + static int32_t freopen(fossil_io_file_t *stream, const std::string &filename, const std::string &mode, FILE *file) { + return fossil_io_file_freopen(stream, filename.c_str(), mode.c_str(), file); } /** @@ -427,13 +427,13 @@ namespace fossil { * * This function opens a file stream, allowing read or write operations on the specified file. * - * @param stream Pointer to the fossil_fstream_t structure to store the opened stream. + * @param stream Pointer to the fossil_io_file_t structure to store the opened stream. * @param filename The name of the file to be opened. * @param mode The mode in which to open the file (e.g., "r" for read, "w" for write). * @return 0 on success, non-zero on failure. */ - static int32_t open(fossil_fstream_t *stream, const char *filename, const char *mode) { - return fossil_fstream_open(stream, filename, mode); + static int32_t open(fossil_io_file_t *stream, const char *filename, const char *mode) { + return fossil_io_file_open(stream, filename, mode); } /** @@ -441,13 +441,13 @@ namespace fossil { * * This function opens a file stream, allowing read or write operations on the specified file. * - * @param stream Pointer to the fossil_fstream_t structure to store the opened stream. + * @param stream Pointer to the fossil_io_file_t structure to store the opened stream. * @param filename The name of the file to be opened. * @param mode The mode in which to open the file (e.g., "r" for read, "w" for write). * @return 0 on success, non-zero on failure. */ - static int32_t open(fossil_fstream_t *stream, const std::string &filename, const std::string &mode) { - return fossil_fstream_open(stream, filename.c_str(), mode.c_str()); + static int32_t open(fossil_io_file_t *stream, const std::string &filename, const std::string &mode) { + return fossil_io_file_open(stream, filename.c_str(), mode.c_str()); } /** @@ -455,10 +455,10 @@ namespace fossil { * * This function closes a previously opened stream, releasing associated resources. * - * @param stream Pointer to the fossil_fstream_t structure to be closed. + * @param stream Pointer to the fossil_io_file_t structure to be closed. */ - static void close(fossil_fstream_t *stream) { - fossil_fstream_close(stream); + static void close(fossil_io_file_t *stream) { + fossil_io_file_close(stream); } /** @@ -466,11 +466,11 @@ namespace fossil { * * This function redirects the given stream to /dev/null, effectively discarding any data written to it. * - * @param stream Pointer to the fossil_fstream_t structure to redirect. + * @param stream Pointer to the fossil_io_file_t structure to redirect. * @return 0 on success, non-zero on failure. */ - static int32_t redirect_to_devnull(fossil_fstream_t *stream) { - return fossil_fstream_redirect_to_devnull(stream); + static int32_t redirect_to_devnull(fossil_io_file_t *stream) { + return fossil_io_file_redirect_to_devnull(stream); } /** @@ -478,11 +478,11 @@ namespace fossil { * * This function checks if a stream is open. * - * @param stream Pointer to the fossil_fstream_t structure to check. + * @param stream Pointer to the fossil_io_file_t structure to check. * @return 1 if the stream is open, 0 if not. */ - static int32_t is_open(const fossil_fstream_t *stream) { - return fossil_fstream_is_open(stream); + static int32_t is_open(const fossil_io_file_t *stream) { + return fossil_io_file_is_open(stream); } /** @@ -490,14 +490,14 @@ namespace fossil { * * This function reads data from an open stream into a buffer. * - * @param stream Pointer to the fossil_fstream_t structure from which to read. + * @param stream Pointer to the fossil_io_file_t structure from which to read. * @param buffer Pointer to the buffer to store the read data. * @param size Size of each element to be read. * @param count Number of elements to read. * @return The total number of elements successfully read. */ - static size_t read(fossil_fstream_t *stream, void *buffer, size_t size, size_t count) { - return fossil_fstream_read(stream, buffer, size, count); + static size_t read(fossil_io_file_t *stream, void *buffer, size_t size, size_t count) { + return fossil_io_file_read(stream, buffer, size, count); } /** @@ -505,14 +505,14 @@ namespace fossil { * * This function writes data from a buffer to an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to which to write. + * @param stream Pointer to the fossil_io_file_t structure to which to write. * @param buffer Pointer to the buffer containing the data to be written. * @param size Size of each element to be written. * @param count Number of elements to write. * @return The total number of elements successfully written. */ - static size_t write(fossil_fstream_t *stream, const void *buffer, size_t size, size_t count) { - return fossil_fstream_write(stream, buffer, size, count); + static size_t write(fossil_io_file_t *stream, const void *buffer, size_t size, size_t count) { + return fossil_io_file_write(stream, buffer, size, count); } /** @@ -520,14 +520,14 @@ namespace fossil { * * This function appends data from a buffer to the end of an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to which to append. + * @param stream Pointer to the fossil_io_file_t structure to which to append. * @param buffer Pointer to the buffer containing the data to be appended. * @param size Size of each element to be appended. * @param count Number of elements to append. * @return 0 on success, non-zero on failure. */ - static int32_t append(fossil_fstream_t *stream, const void *buffer, size_t size, int32_t count) { - return fossil_fstream_append(stream, buffer, size, count); + static int32_t append(fossil_io_file_t *stream, const void *buffer, size_t size, int32_t count) { + return fossil_io_file_append(stream, buffer, size, count); } /** @@ -535,13 +535,13 @@ namespace fossil { * * This function moves the file pointer associated with the stream to a new position. * - * @param stream Pointer to the fossil_fstream_t structure to seek. + * @param stream Pointer to the fossil_io_file_t structure to seek. * @param offset The offset from the specified origin. * @param origin The starting position for the offset (SEEK_SET, SEEK_CUR, SEEK_END). * @return 0 on success, non-zero on failure. */ - static int32_t seek(fossil_fstream_t *stream, int64_t offset, int32_t origin) { - return fossil_fstream_seek(stream, offset, origin); + static int32_t seek(fossil_io_file_t *stream, int64_t offset, int32_t origin) { + return fossil_io_file_seek(stream, offset, origin); } /** @@ -549,11 +549,11 @@ namespace fossil { * * This function retrieves the current position of the file pointer in an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to get the position of. + * @param stream Pointer to the fossil_io_file_t structure to get the position of. * @return The current position of the file pointer. */ - static int32_t tell(fossil_fstream_t *stream) { - return fossil_fstream_tell(stream); + static int32_t tell(fossil_io_file_t *stream) { + return fossil_io_file_tell(stream); } /** @@ -561,12 +561,12 @@ namespace fossil { * * This function saves the contents of an open stream to a new file. * - * @param stream Pointer to the fossil_fstream_t structure to be saved. + * @param stream Pointer to the fossil_io_file_t structure to be saved. * @param new_filename The name of the new file to save to. * @return 0 on success, non-zero on failure. */ - static int32_t save(fossil_fstream_t *stream, const char *new_filename) { - return fossil_fstream_save(stream, new_filename); + static int32_t save(fossil_io_file_t *stream, const char *new_filename) { + return fossil_io_file_save(stream, new_filename); } /** @@ -574,12 +574,12 @@ namespace fossil { * * This function saves the contents of an open stream to a new file. * - * @param stream Pointer to the fossil_fstream_t structure to be saved. + * @param stream Pointer to the fossil_io_file_t structure to be saved. * @param new_filename The name of the new file to save to. * @return 0 on success, non-zero on failure. */ - static int32_t save(fossil_fstream_t *stream, const std::string &new_filename) { - return fossil_fstream_save(stream, new_filename.c_str()); + static int32_t save(fossil_io_file_t *stream, const std::string &new_filename) { + return fossil_io_file_save(stream, new_filename.c_str()); } /** @@ -592,7 +592,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t copy(const char *source_filename, const char *destination_filename) { - return fossil_fstream_copy(source_filename, destination_filename); + return fossil_io_file_copy(source_filename, destination_filename); } /** @@ -605,7 +605,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t copy(const std::string &source_filename, const std::string &destination_filename) { - return fossil_fstream_copy(source_filename.c_str(), destination_filename.c_str()); + return fossil_io_file_copy(source_filename.c_str(), destination_filename.c_str()); } /** @@ -617,7 +617,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t remove(const char *filename) { - return fossil_fstream_remove(filename); + return fossil_io_file_remove(filename); } /** @@ -629,7 +629,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t remove(const std::string &filename) { - return fossil_fstream_remove(filename.c_str()); + return fossil_io_file_remove(filename.c_str()); } /** @@ -642,7 +642,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t rename(const char *old_filename, const char *new_filename) { - return fossil_fstream_rename(old_filename, new_filename); + return fossil_io_file_rename(old_filename, new_filename); } /** @@ -655,7 +655,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t rename(const std::string &old_filename, const std::string &new_filename) { - return fossil_fstream_rename(old_filename.c_str(), new_filename.c_str()); + return fossil_io_file_rename(old_filename.c_str(), new_filename.c_str()); } /** @@ -663,11 +663,11 @@ namespace fossil { * * This function flushes the contents of an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to flush. + * @param stream Pointer to the fossil_io_file_t structure to flush. * @return 0 on success, non-zero on failure. */ - static int32_t flush(fossil_fstream_t *stream) { - return fossil_fstream_flush(stream); + static int32_t flush(fossil_io_file_t *stream) { + return fossil_io_file_flush(stream); } /** @@ -675,11 +675,11 @@ namespace fossil { * * This function moves the file pointer associated with the stream to the beginning. * - * @param stream Pointer to the fossil_fstream_t structure to seek. + * @param stream Pointer to the fossil_io_file_t structure to seek. * @return 0 on success, non-zero on failure. */ - static int32_t setpos(fossil_fstream_t *stream, int32_t pos) { - return fossil_fstream_setpos(stream, pos); + static int32_t setpos(fossil_io_file_t *stream, int32_t pos) { + return fossil_io_file_setpos(stream, pos); } /** @@ -687,12 +687,12 @@ namespace fossil { * * This function retrieves the current position of the file pointer in an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to get the position of. + * @param stream Pointer to the fossil_io_file_t structure to get the position of. * @param pos Pointer to store the current position of the file pointer. * @return 0 on success, non-zero on failure. */ - static int32_t getpos(fossil_fstream_t *stream, int32_t *pos) { - return fossil_fstream_getpos(stream, pos); + static int32_t getpos(fossil_io_file_t *stream, int32_t *pos) { + return fossil_io_file_getpos(stream, pos); } /** @@ -705,7 +705,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t rotate(const char *filename, int32_t n) { - return fossil_fstream_rotate(filename, n); + return fossil_io_file_rotate(filename, n); } /** @@ -718,7 +718,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t rotate(const std::string &filename, int32_t n) { - return fossil_fstream_rotate(filename.c_str(), n); + return fossil_io_file_rotate(filename.c_str(), n); } /** @@ -731,7 +731,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t backup(const char *filename, const char *backup_suffix) { - return fossil_fstream_backup(filename, backup_suffix); + return fossil_io_file_backup(filename, backup_suffix); } /** @@ -744,7 +744,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t backup(const std::string &filename, const std::string &backup_suffix) { - return fossil_fstream_backup(filename.c_str(), backup_suffix.c_str()); + return fossil_io_file_backup(filename.c_str(), backup_suffix.c_str()); } /** @@ -756,7 +756,7 @@ namespace fossil { * @return 1 if the file exists, 0 if not. */ static int32_t file_exists(const char *filename) { - return fossil_fstream_file_exists(filename); + return fossil_io_file_file_exists(filename); } /** @@ -768,7 +768,7 @@ namespace fossil { * @return 1 if the file exists, 0 if not. */ static int32_t file_exists(const std::string &filename) { - return fossil_fstream_file_exists(filename.c_str()); + return fossil_io_file_file_exists(filename.c_str()); } /** @@ -776,11 +776,11 @@ namespace fossil { * * This function retrieves the size of an open stream. * - * @param stream Pointer to the fossil_fstream_t structure to get the size of. + * @param stream Pointer to the fossil_io_file_t structure to get the size of. * @return The size of the open stream. */ - static int32_t get_size(fossil_fstream_t *stream) { - return fossil_fstream_get_size(stream); + static int32_t get_size(fossil_io_file_t *stream) { + return fossil_io_file_get_size(stream); } /** @@ -792,7 +792,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t delete_file(const char *filename) { - return fossil_fstream_delete(filename); + return fossil_io_file_delete(filename); } /** @@ -804,7 +804,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t delete_file(const std::string &filename) { - return fossil_fstream_delete(filename.c_str()); + return fossil_io_file_delete(filename.c_str()); } /** @@ -816,7 +816,7 @@ namespace fossil { * @return The type of the file stream. */ static int get_type(const char *filename) { - return fossil_fstream_get_type(filename); + return fossil_io_file_get_type(filename); } /** @@ -828,7 +828,7 @@ namespace fossil { * @return The type of the file stream. */ static int get_type(const std::string &filename) { - return fossil_fstream_get_type(filename.c_str()); + return fossil_io_file_get_type(filename.c_str()); } /** @@ -838,8 +838,8 @@ namespace fossil { * * @return A pointer to the name of the temporary file, or NULL on failure. */ - static fossil_fstream_t tempfile() { - return fossil_fstream_tempfile(); + static fossil_io_file_t tempfile() { + return fossil_io_file_tempfile(); } /** @@ -851,7 +851,7 @@ namespace fossil { * @return 1 if readable, 0 otherwise. */ static int32_t is_readable(const char *filename) { - return fossil_fstream_is_readable(filename); + return fossil_io_file_is_readable(filename); } /** @@ -863,7 +863,7 @@ namespace fossil { * @return 1 if readable, 0 otherwise. */ static int32_t is_readable(const std::string &filename) { - return fossil_fstream_is_readable(filename.c_str()); + return fossil_io_file_is_readable(filename.c_str()); } /** @@ -875,7 +875,7 @@ namespace fossil { * @return 1 if writable, 0 otherwise. */ static int32_t is_writable(const char *filename) { - return fossil_fstream_is_writable(filename); + return fossil_io_file_is_writable(filename); } /** @@ -887,7 +887,7 @@ namespace fossil { * @return 1 if writable, 0 otherwise. */ static int32_t is_writable(const std::string &filename) { - return fossil_fstream_is_writable(filename.c_str()); + return fossil_io_file_is_writable(filename.c_str()); } /** @@ -899,7 +899,7 @@ namespace fossil { * @return 1 if executable, 0 otherwise. */ static int32_t is_executable(const char *filename) { - return fossil_fstream_is_executable(filename); + return fossil_io_file_is_executable(filename); } /** @@ -911,7 +911,7 @@ namespace fossil { * @return 1 if executable, 0 otherwise. */ static int32_t is_executable(const std::string &filename) { - return fossil_fstream_is_executable(filename.c_str()); + return fossil_io_file_is_executable(filename.c_str()); } /** @@ -924,7 +924,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t set_permissions(const char *filename, int32_t mode) { - return fossil_fstream_set_permissions(filename, mode); + return fossil_io_file_set_permissions(filename, mode); } /** @@ -937,7 +937,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t set_permissions(const std::string &filename, int32_t mode) { - return fossil_fstream_set_permissions(filename.c_str(), mode); + return fossil_io_file_set_permissions(filename.c_str(), mode); } /** @@ -950,7 +950,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t get_permissions(const char *filename, int32_t *mode) { - return fossil_fstream_get_permissions(filename, mode); + return fossil_io_file_get_permissions(filename, mode); } /** @@ -963,7 +963,7 @@ namespace fossil { * @return 0 on success, non-zero on failure. */ static int32_t get_permissions(const std::string &filename, int32_t *mode) { - return fossil_fstream_get_permissions(filename.c_str(), mode); + return fossil_io_file_get_permissions(filename.c_str(), mode); } }; diff --git a/code/logic/fossil/io/input.h b/code/logic/fossil/io/input.h index 50f3d60..ee9b4c2 100644 --- a/code/logic/fossil/io/input.h +++ b/code/logic/fossil/io/input.h @@ -59,7 +59,7 @@ extern "C" { * @param input_stream Pointer to the input stream to read from. * @return The character read as an unsigned char cast to an int, or EOF on end-of-file or error. */ -int fossil_io_getc(fossil_fstream_t *input_stream); +int fossil_io_getc(fossil_io_file_t *input_stream); /** * @brief Trim leading and trailing whitespace from a string in place. @@ -91,7 +91,7 @@ void fossil_io_trim(char *str); * @param input_stream Pointer to the input stream to read from. * @return On success, the function returns 'buf'. If the end-of-file is reached or an error occurs, it returns NULL. */ -char *fossil_io_gets_from_stream(char *buf, size_t size, fossil_fstream_t *input_stream); +char *fossil_io_gets_from_stream(char *buf, size_t size, fossil_io_file_t *input_stream); /** * Reads a line from the input stream with error reporting. @@ -102,7 +102,7 @@ char *fossil_io_gets_from_stream(char *buf, size_t size, fossil_fstream_t *input * @param error_code Pointer to an integer to store the error code (e.g., EOF, input error). * @return On success, the function returns 'buf'. If the end-of-file is reached or an error occurs, it returns NULL. */ -char *fossil_io_gets_from_stream_ex(char *buf, size_t size, fossil_fstream_t *input_stream, int *error_code); +char *fossil_io_gets_from_stream_ex(char *buf, size_t size, fossil_io_file_t *input_stream, int *error_code); /** * Reads formatted input from the standard input stream. @@ -123,7 +123,7 @@ int fossil_io_scanf(const char *format, ...); * @return On success, the number of input items successfully matched and assigned is returned. * On failure, EOF is returned. */ -int fossil_io_fscanf(fossil_fstream_t *input_stream, const char *format, ...); +int fossil_io_fscanf(fossil_io_file_t *input_stream, const char *format, ...); /** * Validates the input buffer and size before reading. @@ -142,7 +142,7 @@ int fossil_io_validate_input_buffer(const char *buf, size_t size); * @param input_stream Pointer to the input stream to read from. * @return On success, the function returns 'buf'. If the end-of-file is reached or an error occurs, it returns NULL. */ -char *fossil_io_gets_utf8(char *buf, size_t size, fossil_fstream_t *input_stream); +char *fossil_io_gets_utf8(char *buf, size_t size, fossil_io_file_t *input_stream); /** * @brief Validates if the input string is a valid integer. @@ -380,7 +380,7 @@ namespace fossil { * @param input_stream Pointer to the input stream to read from. * @return The character read as an unsigned char cast to an int, or EOF on end-of-file or error. */ - static int getc(fossil_fstream_t *input_stream) { + static int getc(fossil_io_file_t *input_stream) { return fossil_io_getc(input_stream); } @@ -416,7 +416,7 @@ namespace fossil { * @param input_stream Pointer to the input stream to read from. * @return On success, the function returns 'buf'. If the end-of-file is reached or an error occurs, it returns NULL. */ - static char *gets_from_stream(char *buf, size_t size, fossil_fstream_t *input_stream) { + static char *gets_from_stream(char *buf, size_t size, fossil_io_file_t *input_stream) { return fossil_io_gets_from_stream(buf, size, input_stream); } @@ -429,7 +429,7 @@ namespace fossil { * @param error_code Pointer to an integer to store the error code (e.g., EOF, input error). * @return On success, the function returns 'buf'. If the end-of-file is reached or an error occurs, it returns NULL. */ - static char *gets_from_stream_ex(char *buf, size_t size, fossil_fstream_t *input_stream, int *error_code) { + static char *gets_from_stream_ex(char *buf, size_t size, fossil_io_file_t *input_stream, int *error_code) { return fossil_io_gets_from_stream_ex(buf, size, input_stream, error_code); } @@ -452,7 +452,7 @@ namespace fossil { * @param input_stream Pointer to the input stream to read from. * @return On success, the function returns 'buf'. If the end-of-file is reached or an error occurs, it returns NULL. */ - static char *gets_utf8(char *buf, size_t size, fossil_fstream_t *input_stream) { + static char *gets_utf8(char *buf, size_t size, fossil_io_file_t *input_stream) { return fossil_io_gets_utf8(buf, size, input_stream); } @@ -495,7 +495,7 @@ namespace fossil { * @return On success, the number of input items successfully matched and assigned is returned. * On failure, EOF is returned. */ - static int fscanf(fossil_fstream_t *input_stream, const char *format, ...) { + static int fscanf(fossil_io_file_t *input_stream, const char *format, ...) { va_list args; va_start(args, format); int result = fossil_io_fscanf(input_stream, format, args); diff --git a/code/logic/fossil/io/output.h b/code/logic/fossil/io/output.h index 34418d3..e715c3c 100644 --- a/code/logic/fossil/io/output.h +++ b/code/logic/fossil/io/output.h @@ -91,7 +91,7 @@ extern int32_t FOSSIL_IO_COLOR_ENABLE; // Flag to enable/disable color output * * @param stream The output stream where subsequent output should be redirected. */ -void fossil_io_redirect_output(fossil_fstream_t *stream); +void fossil_io_redirect_output(fossil_io_file_t *stream); /** * Prints a string to the output. @@ -157,7 +157,7 @@ void fossil_io_putchar(char c); * @param stream The output stream where the string should be printed. This should be a valid pointer to a `FILE` object. * @param str The string to be printed. This should be a null-terminated string. */ -void fossil_io_fputs(fossil_fstream_t *stream, const char *str); +void fossil_io_fputs(fossil_io_file_t *stream, const char *str); /** * Prints a formatted string to the specified output stream. @@ -178,7 +178,7 @@ void fossil_io_fputs(fossil_fstream_t *stream, const char *str); * @param ... The additional arguments to be formatted. These arguments are inserted into the format string * in the order they appear, based on the format specifiers. */ -void fossil_io_fprintf(fossil_fstream_t *stream, const char *format, ...); +void fossil_io_fprintf(fossil_io_file_t *stream, const char *format, ...); // TUI part of the API @@ -303,21 +303,21 @@ namespace fossil { /** * @brief Writes a null-terminated string to a specified fossil output stream. * - * @param stream A pointer to the fossil_fstream_t stream. + * @param stream A pointer to the fossil_io_file_t stream. * @param str A null-terminated C string. */ - static void fputs(fossil_fstream_t *stream, const char *str) { + static void fputs(fossil_io_file_t *stream, const char *str) { fossil_io_fputs(stream, str); } /** * @brief Prints a formatted string to a specified fossil output stream. * - * @param stream A pointer to the fossil_fstream_t stream. + * @param stream A pointer to the fossil_io_file_t stream. * @param format A printf-style format string. * @param ... Additional arguments to be formatted. */ - static void fprintf(fossil_fstream_t *stream, const char *format, ...) { + static void fprintf(fossil_io_file_t *stream, const char *format, ...) { va_list args; va_start(args, format); fossil_io_fprintf(stream, format, args); diff --git a/code/logic/input.c b/code/logic/input.c index cc26a3d..b405c17 100644 --- a/code/logic/input.c +++ b/code/logic/input.c @@ -93,7 +93,7 @@ static int long_base64_run(const char *s, size_t len, size_t threshold) { return 0; } -char *fossil_io_gets_from_stream_ex(char *buf, size_t size, fossil_fstream_t *input_stream, int *error_code) { +char *fossil_io_gets_from_stream_ex(char *buf, size_t size, fossil_io_file_t *input_stream, int *error_code) { if (buf == NULL || size == 0 || input_stream == NULL || error_code == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Invalid buffer, stream, or error code.\n"); return NULL; @@ -197,7 +197,7 @@ void fossil_io_show_progress(int progress) { fflush(stdout); } -int fossil_io_getc(fossil_fstream_t *input_stream) { +int fossil_io_getc(fossil_io_file_t *input_stream) { if (input_stream == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Invalid input stream.\n"); return EOF; @@ -212,7 +212,7 @@ int fossil_io_getc(fossil_fstream_t *input_stream) { } // Function to get a sanitized line of input from a provided stream (or stdin by default) -char *fossil_io_gets_from_stream(char *buf, size_t size, fossil_fstream_t *input_stream) { +char *fossil_io_gets_from_stream(char *buf, size_t size, fossil_io_file_t *input_stream) { if (buf == NULL || size == 0 || input_stream == NULL) { fossil_io_fprintf(FOSSIL_STDERR, "Error: Invalid buffer or stream.\n"); return NULL; @@ -366,7 +366,7 @@ int fossil_io_scanf(const char *format, ...) { return result; } -int fossil_io_fscanf(fossil_fstream_t *input_stream, const char *format, ...) { +int fossil_io_fscanf(fossil_io_file_t *input_stream, const char *format, ...) { va_list args; va_start(args, format); int result = vfscanf(input_stream->file, format, args); @@ -382,7 +382,7 @@ int fossil_io_validate_input_buffer(const char *buf, size_t size) { return 1; } -char *fossil_io_gets_utf8(char *buf, size_t size, fossil_fstream_t *input_stream) { +char *fossil_io_gets_utf8(char *buf, size_t size, fossil_io_file_t *input_stream) { if (!fossil_io_validate_input_buffer(buf, size)) { return NULL; } diff --git a/code/logic/output.c b/code/logic/output.c index 0e700a8..0285c70 100644 --- a/code/logic/output.c +++ b/code/logic/output.c @@ -219,7 +219,7 @@ void fossil_io_print_with_attributes(const char *str) { } // Function to print a sanitized formatted string to a specific file stream with attributes -void fossil_io_fprint_with_attributes(fossil_fstream_t *stream, const char *str) { +void fossil_io_fprint_with_attributes(fossil_io_file_t *stream, const char *str) { if (str != NULL && stream != NULL) { char sanitized_str[FOSSIL_IO_BUFFER_SIZE]; strncpy(sanitized_str, str, sizeof(sanitized_str)); @@ -288,7 +288,7 @@ void fossil_io_printf(const char *format, ...) { } // Function to print a sanitized string to a specific file stream -void fossil_io_fputs(fossil_fstream_t *stream, const char *str) { +void fossil_io_fputs(fossil_io_file_t *stream, const char *str) { if (str != NULL && stream != NULL) { char sanitized_str[FOSSIL_IO_BUFFER_SIZE]; strncpy(sanitized_str, str, sizeof(sanitized_str)); @@ -302,7 +302,7 @@ void fossil_io_fputs(fossil_fstream_t *stream, const char *str) { } // Function to print a sanitized formatted string to a specific file stream -void fossil_io_fprintf(fossil_fstream_t *stream, const char *format, ...) { +void fossil_io_fprintf(fossil_io_file_t *stream, const char *format, ...) { va_list args; va_start(args, format); diff --git a/code/tests/cases/test_archive.c b/code/tests/cases/test_archive.c index e1fdfc5..72aca25 100644 --- a/code/tests/cases/test_archive.c +++ b/code/tests/cases/test_archive.c @@ -64,238 +64,238 @@ FOSSIL_TEST(c_test_archive_get_type_zip) { ASSUME_NOT_CNULL(archive); // Write ZIP signature (PK) to file - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, zip_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, zip_path, "wb")); unsigned char zip_header[] = {0x50, 0x4B, 0x03, 0x04}; - fossil_fstream_write(&stream, zip_header, sizeof(zip_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, zip_header, sizeof(zip_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_close(archive); // Test type detection fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(zip_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_ZIP, detected_type); - fossil_fstream_remove(zip_path); + fossil_io_file_remove(zip_path); } FOSSIL_TEST(c_test_archive_get_type_gzip) { const char *gz_path = "test_type.gz"; // Write GZIP signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, gz_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, gz_path, "wb")); unsigned char gz_header[] = {0x1F, 0x8B, 0x08, 0x00}; - fossil_fstream_write(&stream, gz_header, sizeof(gz_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, gz_header, sizeof(gz_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(gz_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_GZ, detected_type); - fossil_fstream_remove(gz_path); + fossil_io_file_remove(gz_path); } FOSSIL_TEST(c_test_archive_get_type_bzip2) { const char *bz2_path = "test_type.bz2"; // Write BZIP2 signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, bz2_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, bz2_path, "wb")); unsigned char bz2_header[] = {0x42, 0x5A, 0x68, 0x39}; - fossil_fstream_write(&stream, bz2_header, sizeof(bz2_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, bz2_header, sizeof(bz2_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(bz2_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_BZ2, detected_type); - fossil_fstream_remove(bz2_path); + fossil_io_file_remove(bz2_path); } FOSSIL_TEST(c_test_archive_get_type_xz) { const char *xz_path = "test_type.xz"; // Write XZ signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, xz_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, xz_path, "wb")); unsigned char xz_header[] = {0xFD, '7', 'z', 'X', 'Z', 0x00}; - fossil_fstream_write(&stream, xz_header, sizeof(xz_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, xz_header, sizeof(xz_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(xz_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_XZ, detected_type); - fossil_fstream_remove(xz_path); + fossil_io_file_remove(xz_path); } FOSSIL_TEST(c_test_archive_get_type_lz4) { const char *lz4_path = "test_type.lz4"; // Write LZ4 signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, lz4_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, lz4_path, "wb")); unsigned char lz4_header[] = {0x04, 0x22, 0x4D, 0x18}; - fossil_fstream_write(&stream, lz4_header, sizeof(lz4_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, lz4_header, sizeof(lz4_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(lz4_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_LZ4, detected_type); - fossil_fstream_remove(lz4_path); + fossil_io_file_remove(lz4_path); } FOSSIL_TEST(c_test_archive_get_type_zstd) { const char *zst_path = "test_type.zst"; // Write ZSTD signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, zst_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, zst_path, "wb")); unsigned char zst_header[] = {0x28, 0xB5, 0x2F, 0xFD}; - fossil_fstream_write(&stream, zst_header, sizeof(zst_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, zst_header, sizeof(zst_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(zst_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_ZSTD, detected_type); - fossil_fstream_remove(zst_path); + fossil_io_file_remove(zst_path); } FOSSIL_TEST(c_test_archive_get_type_7z) { const char *sz_path = "test_type.7z"; // Write 7Z signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, sz_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, sz_path, "wb")); unsigned char sz_header[] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; - fossil_fstream_write(&stream, sz_header, sizeof(sz_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, sz_header, sizeof(sz_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(sz_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_7Z, detected_type); - fossil_fstream_remove(sz_path); + fossil_io_file_remove(sz_path); } FOSSIL_TEST(c_test_archive_get_type_rar) { const char *rar_path = "test_type.rar"; // Write RAR signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, rar_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, rar_path, "wb")); unsigned char rar_header[] = {'R', 'a', 'r', '!', 0x1A, 0x07, 0x00}; - fossil_fstream_write(&stream, rar_header, sizeof(rar_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, rar_header, sizeof(rar_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(rar_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_RAR, detected_type); - fossil_fstream_remove(rar_path); + fossil_io_file_remove(rar_path); } FOSSIL_TEST(c_test_archive_get_type_rar5) { const char *rar5_path = "test_type.rar5"; // Write RAR5 signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, rar5_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, rar5_path, "wb")); unsigned char rar5_header[] = {'R', 'a', 'r', '!', 0x1A, 0x07, 0x01}; - fossil_fstream_write(&stream, rar5_header, sizeof(rar5_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, rar5_header, sizeof(rar5_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(rar5_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_RAR5, detected_type); - fossil_fstream_remove(rar5_path); + fossil_io_file_remove(rar5_path); } FOSSIL_TEST(c_test_archive_get_type_tar) { const char *tar_path = "test_type.tar"; // Write TAR ustar signature at offset 257 - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, tar_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, tar_path, "wb")); // Write 257 bytes of zeros first unsigned char zeros[257] = {0}; - fossil_fstream_write(&stream, zeros, sizeof(zeros), 1); + fossil_io_file_write(&stream, zeros, sizeof(zeros), 1); // Write ustar signature const char *ustar = "ustar"; - fossil_fstream_write(&stream, ustar, 5, 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, ustar, 5, 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(tar_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_TAR, detected_type); - fossil_fstream_remove(tar_path); + fossil_io_file_remove(tar_path); } FOSSIL_TEST(c_test_archive_get_type_targz) { const char *targz_path = "test_type.tar.gz"; // Write GZIP signature for tar.gz detection - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, targz_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, targz_path, "wb")); unsigned char gz_header[] = {0x1F, 0x8B, 0x08, 0x00}; - fossil_fstream_write(&stream, gz_header, sizeof(gz_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, gz_header, sizeof(gz_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(targz_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_TARGZ, detected_type); - fossil_fstream_remove(targz_path); + fossil_io_file_remove(targz_path); } FOSSIL_TEST(c_test_archive_get_type_cab) { const char *cab_path = "test_type.cab"; // Write CAB signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, cab_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, cab_path, "wb")); unsigned char cab_header[] = {'M', 'S', 'C', 'F'}; - fossil_fstream_write(&stream, cab_header, sizeof(cab_header), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, cab_header, sizeof(cab_header), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(cab_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_CAB, detected_type); - fossil_fstream_remove(cab_path); + fossil_io_file_remove(cab_path); } FOSSIL_TEST(c_test_archive_get_type_iso) { const char *iso_path = "test_type.iso"; // Write ISO 9660 signature at offset 32769 - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, iso_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, iso_path, "wb")); // Write padding to reach offset 32769 unsigned char zeros[32769] = {0}; - fossil_fstream_write(&stream, zeros, sizeof(zeros), 1); + fossil_io_file_write(&stream, zeros, sizeof(zeros), 1); // Write ISO signature const char *iso_sig = "CD001"; - fossil_fstream_write(&stream, iso_sig, 5, 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, iso_sig, 5, 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(iso_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_ISO, detected_type); - fossil_fstream_remove(iso_path); + fossil_io_file_remove(iso_path); } FOSSIL_TEST(c_test_archive_get_type_unknown) { const char *unknown_path = "test_type.unknown"; // Write random data that doesn't match any signature - fossil_fstream_t stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&stream, unknown_path, "wb")); + fossil_io_file_t stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&stream, unknown_path, "wb")); unsigned char random_data[] = {0xDE, 0xAD, 0xBE, 0xEF}; - fossil_fstream_write(&stream, random_data, sizeof(random_data), 1); - fossil_fstream_close(&stream); + fossil_io_file_write(&stream, random_data, sizeof(random_data), 1); + fossil_io_file_close(&stream); fossil_io_archive_type_t detected_type = fossil_io_archive_get_type(unknown_path); ASSUME_ITS_EQUAL_I32(FOSSIL_IO_ARCHIVE_UNKNOWN, detected_type); - fossil_fstream_remove(unknown_path); + fossil_io_file_remove(unknown_path); } FOSSIL_TEST(c_test_archive_get_type_null_path) { @@ -322,7 +322,7 @@ FOSSIL_TEST(c_test_archive_open_and_close) { ASSUME_NOT_CNULL(archive); fossil_io_archive_close(archive); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_create) { @@ -333,7 +333,7 @@ FOSSIL_TEST(c_test_archive_create) { ASSUME_NOT_CNULL(archive); fossil_io_archive_close(archive); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_create_compression_levels) { @@ -352,7 +352,7 @@ FOSSIL_TEST(c_test_archive_create_compression_levels) { fossil_io_archive_t *archive = fossil_io_archive_create(archive_path, FOSSIL_IO_ARCHIVE_ZIP, levels[i]); ASSUME_NOT_CNULL(archive); fossil_io_archive_close(archive); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(archive_path); } } @@ -381,7 +381,7 @@ FOSSIL_TEST(c_test_archive_get_stats_null_params) { ASSUME_ITS_FALSE(fossil_io_archive_get_stats(archive, NULL)); fossil_io_archive_close(archive); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_list_entries) { @@ -396,14 +396,14 @@ FOSSIL_TEST(c_test_archive_list_entries) { const char *test_file1 = "temp_test1.txt"; const char *test_file2 = "temp_test2.txt"; - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file1, "w")); - fossil_fstream_write(&temp_stream, "Content 1", 9, 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file1, "w")); + fossil_io_file_write(&temp_stream, "Content 1", 9, 1); + fossil_io_file_close(&temp_stream); - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file2, "w")); - fossil_fstream_write(&temp_stream, "Content 2", 9, 1); - fossil_fstream_close(&temp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file2, "w")); + fossil_io_file_write(&temp_stream, "Content 2", 9, 1); + fossil_io_file_close(&temp_stream); // Add files to archive ASSUME_ITS_TRUE(fossil_io_archive_add_file(archive, test_file1, "file1.txt")); @@ -433,9 +433,9 @@ FOSSIL_TEST(c_test_archive_list_entries) { fossil_io_archive_close(archive); // Cleanup - fossil_fstream_remove(test_file1); - fossil_fstream_remove(test_file2); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file1); + fossil_io_file_remove(test_file2); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_list_empty) { @@ -450,7 +450,7 @@ FOSSIL_TEST(c_test_archive_list_empty) { ASSUME_ITS_CNULL(entries); fossil_io_archive_close(archive); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_extract_all) { @@ -465,14 +465,14 @@ FOSSIL_TEST(c_test_archive_extract_all) { const char *test_file1 = "temp_all1.txt"; const char *test_file2 = "temp_all2.txt"; - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file1, "w")); - fossil_fstream_write(&temp_stream, "All test 1", 10, 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file1, "w")); + fossil_io_file_write(&temp_stream, "All test 1", 10, 1); + fossil_io_file_close(&temp_stream); - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file2, "w")); - fossil_fstream_write(&temp_stream, "All test 2", 10, 1); - fossil_fstream_close(&temp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file2, "w")); + fossil_io_file_write(&temp_stream, "All test 2", 10, 1); + fossil_io_file_close(&temp_stream); ASSUME_ITS_TRUE(fossil_io_archive_add_file(archive, test_file1, "all1.txt")); ASSUME_ITS_TRUE(fossil_io_archive_add_file(archive, test_file2, "all2.txt")); @@ -485,9 +485,9 @@ FOSSIL_TEST(c_test_archive_extract_all) { fossil_io_archive_close(archive); // Cleanup - fossil_fstream_remove(test_file1); - fossil_fstream_remove(test_file2); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file1); + fossil_io_file_remove(test_file2); + fossil_io_file_remove(archive_path); } // Test modification functions @@ -496,10 +496,10 @@ FOSSIL_TEST(c_test_archive_add_file) { const char *test_file = "temp_add_file.txt"; // Create test file - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file, "w")); - fossil_fstream_write(&temp_stream, "Add file test", 13, 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file, "w")); + fossil_io_file_write(&temp_stream, "Add file test", 13, 1); + fossil_io_file_close(&temp_stream); // Create archive and add file fossil_io_archive_t *archive = fossil_io_archive_create(archive_path, FOSSIL_IO_ARCHIVE_ZIP, FOSSIL_IO_COMPRESSION_NORMAL); @@ -510,8 +510,8 @@ FOSSIL_TEST(c_test_archive_add_file) { ASSUME_ITS_TRUE(fossil_io_archive_exists(archive, "added.txt")); fossil_io_archive_close(archive); - fossil_fstream_remove(test_file); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_add_directory) { @@ -526,17 +526,17 @@ FOSSIL_TEST(c_test_archive_add_directory) { fossil_io_archive_add_directory(archive, test_dir, "testdir"); fossil_io_archive_close(archive); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_add_file_null_params) { const char *archive_path = "test_add_null.zip"; const char *test_file = "temp_add_null.txt"; - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file, "w")); - fossil_fstream_write(&temp_stream, "test", 4, 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file, "w")); + fossil_io_file_write(&temp_stream, "test", 4, 1); + fossil_io_file_close(&temp_stream); fossil_io_archive_t *archive = fossil_io_archive_create(archive_path, FOSSIL_IO_ARCHIVE_ZIP, FOSSIL_IO_COMPRESSION_NORMAL); ASSUME_NOT_CNULL(archive); @@ -547,8 +547,8 @@ FOSSIL_TEST(c_test_archive_add_file_null_params) { ASSUME_ITS_FALSE(fossil_io_archive_add_file(archive, test_file, NULL)); fossil_io_archive_close(archive); - fossil_fstream_remove(test_file); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_remove_entry) { @@ -556,10 +556,10 @@ FOSSIL_TEST(c_test_archive_remove_entry) { const char *test_file = "temp_remove_file.txt"; // Create test file - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file, "w")); - fossil_fstream_write(&temp_stream, "Remove test", 11, 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file, "w")); + fossil_io_file_write(&temp_stream, "Remove test", 11, 1); + fossil_io_file_close(&temp_stream); // Create archive and add file fossil_io_archive_t *archive = fossil_io_archive_create(archive_path, FOSSIL_IO_ARCHIVE_ZIP, FOSSIL_IO_COMPRESSION_NORMAL); @@ -574,8 +574,8 @@ FOSSIL_TEST(c_test_archive_remove_entry) { ASSUME_ITS_FALSE(fossil_io_archive_exists(archive, "to_remove.txt")); fossil_io_archive_close(archive); - fossil_fstream_remove(test_file); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file); + fossil_io_file_remove(archive_path); } // Test utility functions @@ -584,10 +584,10 @@ FOSSIL_TEST(c_test_archive_exists) { const char *test_file = "temp_exists_file.txt"; // Create test file and archive - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file, "w")); - fossil_fstream_write(&temp_stream, "Exists test", 11, 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file, "w")); + fossil_io_file_write(&temp_stream, "Exists test", 11, 1); + fossil_io_file_close(&temp_stream); fossil_io_archive_t *archive = fossil_io_archive_create(archive_path, FOSSIL_IO_ARCHIVE_ZIP, FOSSIL_IO_COMPRESSION_NORMAL); ASSUME_NOT_CNULL(archive); @@ -602,8 +602,8 @@ FOSSIL_TEST(c_test_archive_exists) { ASSUME_ITS_FALSE(fossil_io_archive_exists(archive, NULL)); fossil_io_archive_close(archive); - fossil_fstream_remove(test_file); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_entry_size) { @@ -612,10 +612,10 @@ FOSSIL_TEST(c_test_archive_entry_size) { const char *test_content = "Size test content with known length"; // Create test file - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file, "w")); - fossil_fstream_write(&temp_stream, test_content, strlen(test_content), 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file, "w")); + fossil_io_file_write(&temp_stream, test_content, strlen(test_content), 1); + fossil_io_file_close(&temp_stream); // Create archive and add file fossil_io_archive_t *archive = fossil_io_archive_create(archive_path, FOSSIL_IO_ARCHIVE_ZIP, FOSSIL_IO_COMPRESSION_NORMAL); @@ -635,8 +635,8 @@ FOSSIL_TEST(c_test_archive_entry_size) { ASSUME_ITS_EQUAL_I32(-1, fossil_io_archive_entry_size(archive, NULL)); fossil_io_archive_close(archive); - fossil_fstream_remove(test_file); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file); + fossil_io_file_remove(archive_path); } FOSSIL_TEST(c_test_archive_print) { @@ -644,10 +644,10 @@ FOSSIL_TEST(c_test_archive_print) { const char *test_file = "temp_print_file.txt"; // Create test file and archive - fossil_fstream_t temp_stream; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&temp_stream, test_file, "w")); - fossil_fstream_write(&temp_stream, "Print test", 10, 1); - fossil_fstream_close(&temp_stream); + fossil_io_file_t temp_stream; + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&temp_stream, test_file, "w")); + fossil_io_file_write(&temp_stream, "Print test", 10, 1); + fossil_io_file_close(&temp_stream); fossil_io_archive_t *archive = fossil_io_archive_create(archive_path, FOSSIL_IO_ARCHIVE_ZIP, FOSSIL_IO_COMPRESSION_NORMAL); ASSUME_NOT_CNULL(archive); @@ -660,8 +660,8 @@ FOSSIL_TEST(c_test_archive_print) { fossil_io_archive_print(NULL); fossil_io_archive_close(archive); - fossil_fstream_remove(test_file); - fossil_fstream_remove(archive_path); + fossil_io_file_remove(test_file); + fossil_io_file_remove(archive_path); } // * * * * * * * * * * * * * * * * * * * * * * * * diff --git a/code/tests/cases/test_archive.cpp b/code/tests/cases/test_archive.cpp index 88ae408..1ca6f20 100644 --- a/code/tests/cases/test_archive.cpp +++ b/code/tests/cases/test_archive.cpp @@ -117,7 +117,7 @@ FOSSIL_TEST(cpp_test_archive_class_get_type) { const std::string zip_path = "test_cpp_type.zip"; // Create a ZIP file with header - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, zip_path, "wb")); unsigned char zip_header[] = {0x50, 0x4B, 0x03, 0x04}; fossil::io::Stream::write(&stream, zip_header, sizeof(zip_header), 1); @@ -137,7 +137,7 @@ FOSSIL_TEST(cpp_test_archive_class_extract_all) { const std::string test_file = "temp_cpp_all.txt"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "C++ extract all", 15, 1); fossil::io::Stream::close(&temp_stream); @@ -176,7 +176,7 @@ FOSSIL_TEST(cpp_test_archive_class_exists) { const std::string test_file = "temp_cpp_exists.txt"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "C++ exists test", 15, 1); fossil::io::Stream::close(&temp_stream); @@ -200,7 +200,7 @@ FOSSIL_TEST(cpp_test_archive_class_entry_size) { const std::string content = "C++ entry size test content"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, content.c_str(), content.length(), 1); fossil::io::Stream::close(&temp_stream); @@ -227,7 +227,7 @@ FOSSIL_TEST(cpp_test_archive_class_remove) { const std::string test_file = "temp_cpp_remove.txt"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "C++ remove test", 15, 1); fossil::io::Stream::close(&temp_stream); @@ -253,7 +253,7 @@ FOSSIL_TEST(cpp_test_archive_class_print) { const std::string test_file = "temp_cpp_print.txt"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "C++ print test", 14, 1); fossil::io::Stream::close(&temp_stream); @@ -279,7 +279,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_zip) { ASSUME_NOT_CNULL(archive); // Write ZIP signature (PK) to file - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, zip_path, "wb")); unsigned char zip_header[] = {0x50, 0x4B, 0x03, 0x04}; fossil::io::Stream::write(&stream, zip_header, sizeof(zip_header), 1); @@ -297,7 +297,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_gzip) { const char *gz_path = "test_type.gz"; // Write GZIP signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, gz_path, "wb")); unsigned char gz_header[] = {0x1F, 0x8B, 0x08, 0x00}; fossil::io::Stream::write(&stream, gz_header, sizeof(gz_header), 1); @@ -313,7 +313,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_bzip2) { const char *bz2_path = "test_type.bz2"; // Write BZIP2 signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, bz2_path, "wb")); unsigned char bz2_header[] = {0x42, 0x5A, 0x68, 0x39}; fossil::io::Stream::write(&stream, bz2_header, sizeof(bz2_header), 1); @@ -329,7 +329,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_xz) { const char *xz_path = "test_type.xz"; // Write XZ signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, xz_path, "wb")); unsigned char xz_header[] = {0xFD, '7', 'z', 'X', 'Z', 0x00}; fossil::io::Stream::write(&stream, xz_header, sizeof(xz_header), 1); @@ -345,7 +345,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_lz4) { const char *lz4_path = "test_type.lz4"; // Write LZ4 signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, lz4_path, "wb")); unsigned char lz4_header[] = {0x04, 0x22, 0x4D, 0x18}; fossil::io::Stream::write(&stream, lz4_header, sizeof(lz4_header), 1); @@ -361,7 +361,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_zstd) { const char *zst_path = "test_type.zst"; // Write ZSTD signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, zst_path, "wb")); unsigned char zst_header[] = {0x28, 0xB5, 0x2F, 0xFD}; fossil::io::Stream::write(&stream, zst_header, sizeof(zst_header), 1); @@ -377,7 +377,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_7z) { const char *sz_path = "test_type.7z"; // Write 7Z signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, sz_path, "wb")); unsigned char sz_header[] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; fossil::io::Stream::write(&stream, sz_header, sizeof(sz_header), 1); @@ -393,7 +393,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_rar) { const char *rar_path = "test_type.rar"; // Write RAR signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, rar_path, "wb")); unsigned char rar_header[] = {'R', 'a', 'r', '!', 0x1A, 0x07, 0x00}; fossil::io::Stream::write(&stream, rar_header, sizeof(rar_header), 1); @@ -409,7 +409,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_rar5) { const char *rar5_path = "test_type.rar5"; // Write RAR5 signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, rar5_path, "wb")); unsigned char rar5_header[] = {'R', 'a', 'r', '!', 0x1A, 0x07, 0x01}; fossil::io::Stream::write(&stream, rar5_header, sizeof(rar5_header), 1); @@ -425,7 +425,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_tar) { const char *tar_path = "test_type.tar"; // Write TAR ustar signature at offset 257 - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, tar_path, "wb")); // Write 257 bytes of zeros first @@ -447,7 +447,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_targz) { const char *targz_path = "test_type.tar.gz"; // Write GZIP signature for tar.gz detection - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, targz_path, "wb")); unsigned char gz_header[] = {0x1F, 0x8B, 0x08, 0x00}; fossil::io::Stream::write(&stream, gz_header, sizeof(gz_header), 1); @@ -463,7 +463,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_cab) { const char *cab_path = "test_type.cab"; // Write CAB signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, cab_path, "wb")); unsigned char cab_header[] = {'M', 'S', 'C', 'F'}; fossil::io::Stream::write(&stream, cab_header, sizeof(cab_header), 1); @@ -479,7 +479,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_iso) { const char *iso_path = "test_type.iso"; // Write ISO 9660 signature at offset 32769 - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, iso_path, "wb")); // Write padding to reach offset 32769 @@ -501,7 +501,7 @@ FOSSIL_TEST(cpp_test_archive_get_type_unknown) { const char *unknown_path = "test_type.unknown"; // Write random data that doesn't match any signature - fossil_fstream_t stream; + fossil_io_file_t stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&stream, unknown_path, "wb")); unsigned char random_data[] = {0xDE, 0xAD, 0xBE, 0xEF}; fossil::io::Stream::write(&stream, random_data, sizeof(random_data), 1); @@ -611,7 +611,7 @@ FOSSIL_TEST(cpp_test_archive_list_entries) { const char *test_file1 = "temp_test1.txt"; const char *test_file2 = "temp_test2.txt"; - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file1, "w")); fossil::io::Stream::write(&temp_stream, "Content 1", 9, 1); fossil::io::Stream::close(&temp_stream); @@ -680,7 +680,7 @@ FOSSIL_TEST(cpp_test_archive_extract_all) { const char *test_file1 = "temp_all1.txt"; const char *test_file2 = "temp_all2.txt"; - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file1, "w")); fossil::io::Stream::write(&temp_stream, "All test 1", 10, 1); fossil::io::Stream::close(&temp_stream); @@ -711,7 +711,7 @@ FOSSIL_TEST(cpp_test_archive_add_file) { const char *test_file = "temp_add_file.txt"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "Add file test", 13, 1); fossil::io::Stream::close(&temp_stream); @@ -748,7 +748,7 @@ FOSSIL_TEST(cpp_test_archive_add_file_null_params) { const char *archive_path = "test_add_null.zip"; const char *test_file = "temp_add_null.txt"; - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "test", 4, 1); fossil::io::Stream::close(&temp_stream); @@ -771,7 +771,7 @@ FOSSIL_TEST(cpp_test_archive_remove_entry) { const char *test_file = "temp_remove_file.txt"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "Remove test", 11, 1); fossil::io::Stream::close(&temp_stream); @@ -799,7 +799,7 @@ FOSSIL_TEST(cpp_test_archive_exists) { const char *test_file = "temp_exists_file.txt"; // Create test file and archive - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "Exists test", 11, 1); fossil::io::Stream::close(&temp_stream); @@ -827,7 +827,7 @@ FOSSIL_TEST(cpp_test_archive_entry_size) { const char *test_content = "Size test content with known length"; // Create test file - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, test_content, strlen(test_content), 1); fossil::io::Stream::close(&temp_stream); @@ -859,7 +859,7 @@ FOSSIL_TEST(cpp_test_archive_print) { const char *test_file = "temp_print_file.txt"; // Create test file and archive - fossil_fstream_t temp_stream; + fossil_io_file_t temp_stream; ASSUME_ITS_EQUAL_I32(0, fossil::io::Stream::open(&temp_stream, test_file, "w")); fossil::io::Stream::write(&temp_stream, "Print test", 10, 1); fossil::io::Stream::close(&temp_stream); diff --git a/code/tests/cases/test_cstring.cpp b/code/tests/cases/test_cstring.cpp index c103e0b..b243df2 100644 --- a/code/tests/cases/test_cstring.cpp +++ b/code/tests/cases/test_cstring.cpp @@ -36,7 +36,7 @@ // Define the test suite and add test cases FOSSIL_SUITE(cpp_string_suite); -fossil_fstream_t cpp_string; +fossil_io_file_t cpp_string; // Setup function for the test suite FOSSIL_SETUP(cpp_string_suite) { diff --git a/code/tests/cases/test_cstring.mm b/code/tests/cases/test_cstring.mm index c13c2e8..f0c80bd 100644 --- a/code/tests/cases/test_cstring.mm +++ b/code/tests/cases/test_cstring.mm @@ -36,7 +36,7 @@ // Define the test suite and add test cases FOSSIL_SUITE(objcpp_string_suite); -fossil_fstream_t objcpp_string; +fossil_io_file_t objcpp_string; // Setup function for the test suite FOSSIL_SETUP(objcpp_string_suite) { diff --git a/code/tests/cases/test_input.c b/code/tests/cases/test_input.c index 0b29ec8..67d6a6f 100644 --- a/code/tests/cases/test_input.c +++ b/code/tests/cases/test_input.c @@ -110,7 +110,7 @@ FOSSIL_TEST(c_test_io_trim_whitespace_middle_preserved) { FOSSIL_TEST(c_test_io_gets_from_stream) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -126,7 +126,7 @@ FOSSIL_TEST(c_test_io_gets_from_stream_no_offensive) { char expected[] = "This is a clean sentence."; char buffer[256]; - fossil_fstream_t stream = {tmpfile(), "tempfile"}; + fossil_io_file_t stream = {tmpfile(), "tempfile"}; fwrite(input, 1, strlen(input), stream.file); rewind(stream.file); char *result = fossil_io_gets_from_stream(buffer, sizeof(buffer), &stream); @@ -140,7 +140,7 @@ FOSSIL_TEST(c_test_io_gets_from_stream_with_punctuation) { char expected[] = "This is a test with punctuation, and special characters!"; char buffer[256]; - fossil_fstream_t stream = {tmpfile(), "tempfile"}; + fossil_io_file_t stream = {tmpfile(), "tempfile"}; fwrite(input, 1, strlen(input), stream.file); rewind(stream.file); char *result = fossil_io_gets_from_stream(buffer, sizeof(buffer), &stream); @@ -151,7 +151,7 @@ FOSSIL_TEST(c_test_io_gets_from_stream_with_punctuation) { FOSSIL_TEST(c_test_io_gets_from_stream_empty_input) { const char *input_data = "\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -164,7 +164,7 @@ FOSSIL_TEST(c_test_io_gets_from_stream_empty_input) { FOSSIL_TEST(c_test_io_gets_from_stream_only_whitespace) { const char *input_data = " \n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -177,7 +177,7 @@ FOSSIL_TEST(c_test_io_gets_from_stream_only_whitespace) { FOSSIL_TEST(c_test_io_gets_from_stream_long_input) { const char *input_data = "This is a very long input string that exceeds the buffer size\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -190,7 +190,7 @@ FOSSIL_TEST(c_test_io_gets_from_stream_long_input) { FOSSIL_TEST(c_test_io_gets_from_stream_ex) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -204,7 +204,7 @@ FOSSIL_TEST(c_test_io_gets_from_stream_ex) { FOSSIL_TEST(c_test_io_gets_utf8) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -275,7 +275,7 @@ FOSSIL_TEST(c_test_io_validate_is_length_invalid) { FOSSIL_TEST(c_test_io_getc) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); diff --git a/code/tests/cases/test_input.cpp b/code/tests/cases/test_input.cpp index eab4293..d23c2e3 100644 --- a/code/tests/cases/test_input.cpp +++ b/code/tests/cases/test_input.cpp @@ -56,7 +56,7 @@ FOSSIL_TEARDOWN(cpp_input_suite) { FOSSIL_TEST(cpp_test_io_gets_from_stream) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "test_input_stream"); @@ -75,7 +75,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_no_offensive) { char expected[] = "This is a clean sentence."; char buffer[256]; - fossil_fstream_t stream; + fossil_io_file_t stream; stream.file = tmpfile(); strcpy(stream.filename, "clean_sentence_stream"); @@ -92,7 +92,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_with_punctuation) { char expected[] = "This is a test with punctuation, and special characters!"; char buffer[256]; - fossil_fstream_t stream; + fossil_io_file_t stream; stream.file = tmpfile(); strcpy(stream.filename, "punctuation_stream"); @@ -106,7 +106,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_with_punctuation) { FOSSIL_TEST(cpp_test_io_gets_from_stream_empty_input) { const char *input_data = "\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "empty_input_stream"); @@ -122,7 +122,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_empty_input) { FOSSIL_TEST(cpp_test_io_gets_from_stream_only_whitespace) { const char *input_data = " \n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "whitespace_stream"); @@ -138,7 +138,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_only_whitespace) { FOSSIL_TEST(cpp_test_io_gets_from_stream_long_input) { const char *input_data = "This is a very long input string that exceeds the buffer size\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "long_input_stream"); @@ -154,7 +154,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_long_input) { FOSSIL_TEST(cpp_test_io_gets_from_stream_ex) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "stream_ex"); @@ -171,7 +171,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_ex) { FOSSIL_TEST(cpp_test_io_gets_utf8) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "utf8_stream"); @@ -187,7 +187,7 @@ FOSSIL_TEST(cpp_test_io_gets_utf8) { FOSSIL_TEST(cpp_test_io_gets_from_stream_class) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "class_stream"); @@ -203,7 +203,7 @@ FOSSIL_TEST(cpp_test_io_gets_from_stream_class) { FOSSIL_TEST(cpp_test_io_gets_from_stream_ex_class) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "class_stream_ex"); @@ -227,7 +227,7 @@ FOSSIL_TEST(cpp_test_io_validate_input_buffer_class) { FOSSIL_TEST(cpp_test_io_gets_utf8_class) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "utf8_class_stream"); @@ -301,7 +301,7 @@ FOSSIL_TEST(cpp_test_io_validate_is_length_invalid) { FOSSIL_TEST(cpp_test_io_input_class_gets_from_stream) { const char *input_data = "input data\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "input_stream"); @@ -317,7 +317,7 @@ FOSSIL_TEST(cpp_test_io_input_class_gets_from_stream) { FOSSIL_TEST(cpp_test_io_input_class_gets_from_stream_ex) { const char *input_data = "input data\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "input_stream_ex"); @@ -348,7 +348,7 @@ FOSSIL_TEST(cpp_test_io_input_class_validate_input_buffer_invalid) { FOSSIL_TEST(cpp_test_io_input_class_gets_utf8_valid) { const char *input_data = "utf8 valid input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "utf8_valid_stream"); @@ -364,7 +364,7 @@ FOSSIL_TEST(cpp_test_io_input_class_gets_utf8_valid) { FOSSIL_TEST(cpp_test_io_input_class_gets_from_stream_empty) { const char *input_data = "\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "empty_stream"); @@ -380,7 +380,7 @@ FOSSIL_TEST(cpp_test_io_input_class_gets_from_stream_empty) { FOSSIL_TEST(cpp_test_io_input_class_gets_from_stream_whitespace_only) { const char *input_data = " \n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "whitespace_stream"); @@ -396,7 +396,7 @@ FOSSIL_TEST(cpp_test_io_input_class_gets_from_stream_whitespace_only) { FOSSIL_TEST(cpp_test_io_getc) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "getc_stream"); diff --git a/code/tests/cases/test_input.m b/code/tests/cases/test_input.m index 7ba67b0..e12b58a 100644 --- a/code/tests/cases/test_input.m +++ b/code/tests/cases/test_input.m @@ -110,7 +110,7 @@ FOSSIL_TEST(objc_test_io_gets_from_stream) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -126,7 +126,7 @@ char expected[] = "This is a clean sentence."; char buffer[256]; - fossil_fstream_t stream = {tmpfile(), "tempfile"}; + fossil_io_file_t stream = {tmpfile(), "tempfile"}; fwrite(input, 1, strlen(input), stream.file); rewind(stream.file); char *result = fossil_io_gets_from_stream(buffer, sizeof(buffer), &stream); @@ -140,7 +140,7 @@ char expected[] = "This is a test with punctuation, and special characters!"; char buffer[256]; - fossil_fstream_t stream = {tmpfile(), "tempfile"}; + fossil_io_file_t stream = {tmpfile(), "tempfile"}; fwrite(input, 1, strlen(input), stream.file); rewind(stream.file); char *result = fossil_io_gets_from_stream(buffer, sizeof(buffer), &stream); @@ -151,7 +151,7 @@ FOSSIL_TEST(objc_test_io_gets_from_stream_empty_input) { const char *input_data = "\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -164,7 +164,7 @@ FOSSIL_TEST(objc_test_io_gets_from_stream_only_whitespace) { const char *input_data = " \n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -177,7 +177,7 @@ FOSSIL_TEST(objc_test_io_gets_from_stream_long_input) { const char *input_data = "This is a very long input string that exceeds the buffer size\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -190,7 +190,7 @@ FOSSIL_TEST(objc_test_io_gets_from_stream_ex) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -204,7 +204,7 @@ FOSSIL_TEST(objc_test_io_gets_utf8) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); @@ -275,7 +275,7 @@ FOSSIL_TEST(objc_test_io_getc) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream = {tmpfile(), "tempfile"}; + fossil_io_file_t input_stream = {tmpfile(), "tempfile"}; fwrite(input_data, 1, strlen(input_data), input_stream.file); rewind(input_stream.file); diff --git a/code/tests/cases/test_input.mm b/code/tests/cases/test_input.mm index 01e4361..5a5edb5 100644 --- a/code/tests/cases/test_input.mm +++ b/code/tests/cases/test_input.mm @@ -56,7 +56,7 @@ FOSSIL_TEST(objcpp_test_io_gets_from_stream) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "test_input_stream"); @@ -75,7 +75,7 @@ char expected[] = "This is a clean sentence."; char buffer[256]; - fossil_fstream_t stream; + fossil_io_file_t stream; stream.file = tmpfile(); strcpy(stream.filename, "clean_sentence_stream"); @@ -92,7 +92,7 @@ char expected[] = "This is a test with punctuation, and special characters!"; char buffer[256]; - fossil_fstream_t stream; + fossil_io_file_t stream; stream.file = tmpfile(); strcpy(stream.filename, "punctuation_stream"); @@ -106,7 +106,7 @@ FOSSIL_TEST(objcpp_test_io_gets_from_stream_empty_input) { const char *input_data = "\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "empty_input_stream"); @@ -122,7 +122,7 @@ FOSSIL_TEST(objcpp_test_io_gets_from_stream_only_whitespace) { const char *input_data = " \n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "whitespace_stream"); @@ -138,7 +138,7 @@ FOSSIL_TEST(objcpp_test_io_gets_from_stream_long_input) { const char *input_data = "This is a very long input string that exceeds the buffer size\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "long_input_stream"); @@ -154,7 +154,7 @@ FOSSIL_TEST(objcpp_test_io_gets_from_stream_ex) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "stream_ex"); @@ -171,7 +171,7 @@ FOSSIL_TEST(objcpp_test_io_gets_utf8) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "utf8_stream"); @@ -187,7 +187,7 @@ FOSSIL_TEST(objcpp_test_io_gets_from_stream_class) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "class_stream"); @@ -203,7 +203,7 @@ FOSSIL_TEST(objcpp_test_io_gets_from_stream_ex_class) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "class_stream_ex"); @@ -227,7 +227,7 @@ FOSSIL_TEST(objcpp_test_io_gets_utf8_class) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "utf8_class_stream"); @@ -301,7 +301,7 @@ FOSSIL_TEST(objcpp_test_io_input_class_gets_from_stream) { const char *input_data = "input data\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "input_stream"); @@ -317,7 +317,7 @@ FOSSIL_TEST(objcpp_test_io_input_class_gets_from_stream_ex) { const char *input_data = "input data\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "input_stream_ex"); @@ -348,7 +348,7 @@ FOSSIL_TEST(objcpp_test_io_input_class_gets_utf8_valid) { const char *input_data = "utf8 valid input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "utf8_valid_stream"); @@ -364,7 +364,7 @@ FOSSIL_TEST(objcpp_test_io_input_class_gets_from_stream_empty) { const char *input_data = "\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "empty_stream"); @@ -380,7 +380,7 @@ FOSSIL_TEST(objcpp_test_io_input_class_gets_from_stream_whitespace_only) { const char *input_data = " \n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "whitespace_stream"); @@ -396,7 +396,7 @@ FOSSIL_TEST(objcpp_test_io_getc) { const char *input_data = "test input\n"; - fossil_fstream_t input_stream; + fossil_io_file_t input_stream; input_stream.file = tmpfile(); strcpy(input_stream.filename, "getc_stream"); diff --git a/code/tests/cases/test_stream.c b/code/tests/cases/test_stream.c index 0c45c4d..9884d4d 100644 --- a/code/tests/cases/test_stream.c +++ b/code/tests/cases/test_stream.c @@ -36,7 +36,7 @@ // Define the test suite and add test cases FOSSIL_SUITE(c_stream_suite); -fossil_fstream_t c_stream; +fossil_io_file_t c_stream; // Setup function for the test suite FOSSIL_SETUP(c_stream_suite) { @@ -58,27 +58,27 @@ FOSSIL_TEARDOWN(c_stream_suite) { FOSSIL_TEST(c_test_stream_tempfile_creation) { // Create a temporary file - fossil_fstream_t temp_stream = fossil_fstream_tempfile(); + fossil_io_file_t temp_stream = fossil_io_file_tempfile(); // Check if the temporary file is open - ASSUME_ITS_TRUE(fossil_fstream_is_open(&temp_stream)); + ASSUME_ITS_TRUE(fossil_io_file_is_open(&temp_stream)); // Close the temporary file - fossil_fstream_close(&temp_stream); + fossil_io_file_close(&temp_stream); } FOSSIL_TEST(c_test_stream_tempfile_cleanup) { // Create a temporary file - fossil_fstream_t temp_stream = fossil_fstream_tempfile(); + fossil_io_file_t temp_stream = fossil_io_file_tempfile(); // Get the temporary file name const char *temp_filename = temp_stream.filename; // Close the temporary file - fossil_fstream_close(&temp_stream); + fossil_io_file_close(&temp_stream); // Verify the temporary file is deleted - ASSUME_NOT_EQUAL_I32(0, fossil_fstream_file_exists(temp_filename)); + ASSUME_NOT_EQUAL_I32(0, fossil_io_file_file_exists(temp_filename)); } FOSSIL_TEST(c_test_stream_let_write_and_read_file) { @@ -86,15 +86,15 @@ FOSSIL_TEST(c_test_stream_let_write_and_read_file) { const char *content = "This is a test."; // Write data to the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_write(&c_stream, content, strlen(content), 1); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_write(&c_stream, content, strlen(content), 1); + fossil_io_file_close(&c_stream); // Read data from the file char buffer[1024]; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "r")); - fossil_fstream_read(&c_stream, buffer, sizeof(buffer), 1); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "r")); + fossil_io_file_read(&c_stream, buffer, sizeof(buffer), 1); + fossil_io_file_close(&c_stream); } FOSSIL_TEST(c_test_stream_redirect_to_devnull) { @@ -102,24 +102,24 @@ FOSSIL_TEST(c_test_stream_redirect_to_devnull) { const char *content = "This is a test."; // Create the file and write data to it - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_write(&c_stream, content, strlen(content), 1); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_write(&c_stream, content, strlen(content), 1); // Redirect the stream to /dev/null - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_redirect_to_devnull(&c_stream)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_redirect_to_devnull(&c_stream)); // Attempt to write more data (should not affect the file) const char *extra_content = "This should not be written."; - fossil_fstream_write(&c_stream, extra_content, strlen(extra_content), 1); + fossil_io_file_write(&c_stream, extra_content, strlen(extra_content), 1); // Close the stream - fossil_fstream_close(&c_stream); + fossil_io_file_close(&c_stream); // Reopen the file and verify its content remains unchanged char buffer[1024] = {0}; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "r")); - fossil_fstream_read(&c_stream, buffer, sizeof(buffer), 1); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "r")); + fossil_io_file_read(&c_stream, buffer, sizeof(buffer), 1); + fossil_io_file_close(&c_stream); ASSUME_ITS_EQUAL_CSTR(content, buffer); } @@ -129,8 +129,8 @@ FOSSIL_TEST(c_test_stream_let_open_and_close_file) { const char *filename = "testfile.txt"; // Open the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_close(&c_stream); } FOSSIL_TEST(c_test_stream_multiple_files) { @@ -138,12 +138,12 @@ FOSSIL_TEST(c_test_stream_multiple_files) { const char *filename2 = "testfile2.txt"; // Open the first file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename1, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename1, "w")); + fossil_io_file_close(&c_stream); // Open the second file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename2, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename2, "w")); + fossil_io_file_close(&c_stream); } FOSSIL_TEST(c_test_stream_seek_and_tell) { @@ -151,82 +151,82 @@ FOSSIL_TEST(c_test_stream_seek_and_tell) { const char *content = "This is a test."; // Write data to the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_write(&c_stream, content, strlen(content), 1); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_write(&c_stream, content, strlen(content), 1); + fossil_io_file_close(&c_stream); // Open the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "r")); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "r")); // Seek to the end of the file - fossil_fstream_seek(&c_stream, 0, SEEK_END); + fossil_io_file_seek(&c_stream, 0, SEEK_END); // Get the current position - long position = fossil_fstream_tell(&c_stream); + long position = fossil_io_file_tell(&c_stream); ASSUME_ITS_TRUE(position > 0); // Close the file - fossil_fstream_close(&c_stream); + fossil_io_file_close(&c_stream); } FOSSIL_TEST(c_test_stream_get_type) { const char *filename = "testfile_type.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_close(&c_stream); // Check the file type - ASSUME_ITS_EQUAL_I32(2, fossil_fstream_get_type(filename)); // Regular file + ASSUME_ITS_EQUAL_I32(2, fossil_io_file_get_type(filename)); // Regular file } FOSSIL_TEST(c_test_stream_is_readable) { const char *filename = "testfile_readable.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_close(&c_stream); // Check if the file is readable - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_readable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_readable(filename)); } FOSSIL_TEST(c_test_stream_is_writable) { const char *filename = "testfile_writable.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_close(&c_stream); // Check if the file is writable - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_writable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_writable(filename)); } FOSSIL_TEST(c_test_stream_is_executable) { const char *filename = "testfile_executable.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_close(&c_stream); // Check if the file is executable - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_is_executable(filename)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_is_executable(filename)); } FOSSIL_TEST(c_test_stream_set_permissions) { const char *filename = "testfile_permissions.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_close(&c_stream); // Set file permissions - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_set_permissions(filename, 0644)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_set_permissions(filename, 0644)); // Check if the file is readable and writable - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_readable(filename)); - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_writable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_readable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_writable(filename)); } FOSSIL_TEST(c_test_stream_get_permissions) { @@ -234,14 +234,14 @@ FOSSIL_TEST(c_test_stream_get_permissions) { int32_t mode; // // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_close(&c_stream); // Set file permissions - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_set_permissions(filename, 0644)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_set_permissions(filename, 0644)); // Get file permissions - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_get_permissions(filename, &mode)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_get_permissions(filename, &mode)); } FOSSIL_TEST(c_test_stream_flush_file) { @@ -249,12 +249,12 @@ FOSSIL_TEST(c_test_stream_flush_file) { const char *content = "This is a test."; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_write(&c_stream, content, strlen(content), 1); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_write(&c_stream, content, strlen(content), 1); // Flush the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_flush(&c_stream)); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_flush(&c_stream)); + fossil_io_file_close(&c_stream); } FOSSIL_TEST(c_test_stream_setpos_and_getpos) { @@ -263,22 +263,22 @@ FOSSIL_TEST(c_test_stream_setpos_and_getpos) { int32_t pos; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "w")); - fossil_fstream_write(&c_stream, content, strlen(content), 1); - fossil_fstream_close(&c_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "w")); + fossil_io_file_write(&c_stream, content, strlen(content), 1); + fossil_io_file_close(&c_stream); // Open the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&c_stream, filename, "r")); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&c_stream, filename, "r")); // Set the file position - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_setpos(&c_stream, 5)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_setpos(&c_stream, 5)); // Get the file position - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_getpos(&c_stream, &pos)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_getpos(&c_stream, &pos)); ASSUME_ITS_EQUAL_I32(5, pos); // Close the file - fossil_fstream_close(&c_stream); + fossil_io_file_close(&c_stream); } // * * * * * * * * * * * * * * * * * * * * * * * * diff --git a/code/tests/cases/test_stream.cpp b/code/tests/cases/test_stream.cpp index d0bdc77..6661cbb 100644 --- a/code/tests/cases/test_stream.cpp +++ b/code/tests/cases/test_stream.cpp @@ -36,7 +36,7 @@ // Define the test suite and add test cases FOSSIL_SUITE(cpp_stream_suite); -fossil_fstream_t cpp_stream; +fossil_io_file_t cpp_stream; // Setup function for the test suite FOSSIL_SETUP(cpp_stream_suite) { @@ -58,27 +58,27 @@ FOSSIL_TEARDOWN(cpp_stream_suite) { FOSSIL_TEST(cpp_test_stream_tempfile_creation) { // Create a temporary file - fossil_fstream_t temp_stream = fossil_fstream_tempfile(); + fossil_io_file_t temp_stream = fossil_io_file_tempfile(); // Check if the temporary file is open - ASSUME_ITS_TRUE(fossil_fstream_is_open(&temp_stream)); + ASSUME_ITS_TRUE(fossil_io_file_is_open(&temp_stream)); // Close the temporary file - fossil_fstream_close(&temp_stream); + fossil_io_file_close(&temp_stream); } FOSSIL_TEST(cpp_test_stream_tempfile_cleanup) { // Create a temporary file - fossil_fstream_t temp_stream = fossil_fstream_tempfile(); + fossil_io_file_t temp_stream = fossil_io_file_tempfile(); // Get the temporary file name const char *temp_filename = temp_stream.filename; // Close the temporary file - fossil_fstream_close(&temp_stream); + fossil_io_file_close(&temp_stream); // Verify the temporary file is deleted - ASSUME_NOT_EQUAL_I32(0, fossil_fstream_file_exists(temp_filename)); + ASSUME_NOT_EQUAL_I32(0, fossil_io_file_file_exists(temp_filename)); } FOSSIL_TEST(cpp_test_stream_let_write_and_read_file) { @@ -86,23 +86,23 @@ FOSSIL_TEST(cpp_test_stream_let_write_and_read_file) { const char *content = "This is a test."; // Write data to the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_write(&cpp_stream, content, strlen(content), 1); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_write(&cpp_stream, content, strlen(content), 1); + fossil_io_file_close(&cpp_stream); // Read data from the file char buffer[1024]; - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "r")); - fossil_fstream_read(&cpp_stream, buffer, sizeof(buffer), 1); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "r")); + fossil_io_file_read(&cpp_stream, buffer, sizeof(buffer), 1); + fossil_io_file_close(&cpp_stream); } FOSSIL_TEST(cpp_test_stream_let_open_and_close_file) { const char *filename = "testfile.txt"; // Open the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_close(&cpp_stream); } FOSSIL_TEST(cpp_test_stream_multiple_files) { @@ -110,12 +110,12 @@ FOSSIL_TEST(cpp_test_stream_multiple_files) { const char *filename2 = "testfile2.txt"; // Open the first file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename1, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename1, "w")); + fossil_io_file_close(&cpp_stream); // Open the second file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename2, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename2, "w")); + fossil_io_file_close(&cpp_stream); } FOSSIL_TEST(cpp_test_stream_seek_and_tell) { @@ -123,82 +123,82 @@ FOSSIL_TEST(cpp_test_stream_seek_and_tell) { const char *content = "This is a test."; // Write data to the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_write(&cpp_stream, content, strlen(content), 1); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_write(&cpp_stream, content, strlen(content), 1); + fossil_io_file_close(&cpp_stream); // Open the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "r")); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "r")); // Seek to the end of the file - fossil_fstream_seek(&cpp_stream, 0, SEEK_END); + fossil_io_file_seek(&cpp_stream, 0, SEEK_END); // Get the current position - long position = fossil_fstream_tell(&cpp_stream); + long position = fossil_io_file_tell(&cpp_stream); ASSUME_ITS_TRUE(position > 0); // Close the file - fossil_fstream_close(&cpp_stream); + fossil_io_file_close(&cpp_stream); } FOSSIL_TEST(cpp_test_stream_get_type) { const char *filename = "testfile_type.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_close(&cpp_stream); // Check the file type - ASSUME_ITS_EQUAL_I32(2, fossil_fstream_get_type(filename)); // Regular file + ASSUME_ITS_EQUAL_I32(2, fossil_io_file_get_type(filename)); // Regular file } FOSSIL_TEST(cpp_test_stream_is_readable) { const char *filename = "testfile_readable.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_close(&cpp_stream); // Check if the file is readable - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_readable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_readable(filename)); } FOSSIL_TEST(cpp_test_stream_is_writable) { const char *filename = "testfile_writable.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_close(&cpp_stream); // Check if the file is writable - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_writable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_writable(filename)); } FOSSIL_TEST(cpp_test_stream_is_executable) { const char *filename = "testfile_executable.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_close(&cpp_stream); // Check if the file is executable - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_is_executable(filename)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_is_executable(filename)); } FOSSIL_TEST(cpp_test_stream_set_permissions) { const char *filename = "testfile_permissions.txt"; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_close(&cpp_stream); // Set file permissions - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_set_permissions(filename, 0644)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_set_permissions(filename, 0644)); // Check if the file is readable and writable - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_readable(filename)); - ASSUME_ITS_EQUAL_I32(1, fossil_fstream_is_writable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_readable(filename)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_file_is_writable(filename)); } FOSSIL_TEST(cpp_test_stream_get_permissions) { @@ -206,14 +206,14 @@ FOSSIL_TEST(cpp_test_stream_get_permissions) { int32_t mode; // // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_close(&cpp_stream); // Set file permissions - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_set_permissions(filename, 0644)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_set_permissions(filename, 0644)); // Get file permissions - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_get_permissions(filename, &mode)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_get_permissions(filename, &mode)); } FOSSIL_TEST(cpp_test_stream_remove_file) { @@ -221,23 +221,23 @@ FOSSIL_TEST(cpp_test_stream_remove_file) { const char *content = "This is a test."; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_write(&cpp_stream, content, strlen(content), 1); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_write(&cpp_stream, content, strlen(content), 1); + fossil_io_file_close(&cpp_stream); // Remove the file - int32_t remove_result = fossil_fstream_remove(filename); + int32_t remove_result = fossil_io_file_remove(filename); ASSUME_ITS_EQUAL_I32(FOSSIL_ERROR_OK, remove_result); // Check if the file does not exist - ASSUME_ITS_EQUAL_I32(FOSSIL_ERROR_OK, fossil_fstream_file_exists(filename)); + ASSUME_ITS_EQUAL_I32(FOSSIL_ERROR_OK, fossil_io_file_file_exists(filename)); // Try removing again, should return FOSSIL_ERROR_FILE_NOT_FOUND - int32_t remove_again_result = fossil_fstream_remove(filename); + int32_t remove_again_result = fossil_io_file_remove(filename); ASSUME_ITS_EQUAL_I32(FOSSIL_ERROR_FILE_NOT_FOUND, remove_again_result); // Try removing with NULL, should return FOSSIL_ERROR_CNULL_POINTER - int32_t remove_null_result = fossil_fstream_remove(NULL); + int32_t remove_null_result = fossil_io_file_remove(NULL); ASSUME_ITS_EQUAL_I32(FOSSIL_ERROR_CNULL_POINTER, remove_null_result); } @@ -246,12 +246,12 @@ FOSSIL_TEST(cpp_test_stream_flush_file) { const char *content = "This is a test."; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_write(&cpp_stream, content, strlen(content), 1); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_write(&cpp_stream, content, strlen(content), 1); // Flush the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_flush(&cpp_stream)); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_flush(&cpp_stream)); + fossil_io_file_close(&cpp_stream); } FOSSIL_TEST(cpp_test_stream_setpos_and_getpos) { @@ -260,27 +260,27 @@ FOSSIL_TEST(cpp_test_stream_setpos_and_getpos) { int32_t pos; // Create the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "w")); - fossil_fstream_write(&cpp_stream, content, strlen(content), 1); - fossil_fstream_close(&cpp_stream); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "w")); + fossil_io_file_write(&cpp_stream, content, strlen(content), 1); + fossil_io_file_close(&cpp_stream); // Open the file - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_open(&cpp_stream, filename, "r")); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_open(&cpp_stream, filename, "r")); // Set the file position - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_setpos(&cpp_stream, 5)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_setpos(&cpp_stream, 5)); // Get the file position - ASSUME_ITS_EQUAL_I32(0, fossil_fstream_getpos(&cpp_stream, &pos)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_file_getpos(&cpp_stream, &pos)); ASSUME_ITS_EQUAL_I32(5, pos); // Close the file - fossil_fstream_close(&cpp_stream); + fossil_io_file_close(&cpp_stream); } FOSSIL_TEST(cpp_test_stream_class_tempfile_creation) { // Create a temporary file using the class method - fossil_fstream_t temp_stream = fossil::io::Stream::tempfile(); + fossil_io_file_t temp_stream = fossil::io::Stream::tempfile(); // Check if the temporary file is open ASSUME_ITS_TRUE(fossil::io::Stream::is_open(&temp_stream)); @@ -291,7 +291,7 @@ FOSSIL_TEST(cpp_test_stream_class_tempfile_creation) { FOSSIL_TEST(cpp_test_stream_class_tempfile_cleanup) { // Create a temporary file using the class method - fossil_fstream_t temp_stream = fossil::io::Stream::tempfile(); + fossil_io_file_t temp_stream = fossil::io::Stream::tempfile(); // Get the temporary file name const char *temp_filename = temp_stream.filename; From 8deb6d804c4ab642bdfb124afd304dea9a068fcc Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 17:10:07 -0600 Subject: [PATCH 10/21] rename fstream to io_file --- code/logic/fossil/io/framework.h | 2 +- code/logic/meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/logic/fossil/io/framework.h b/code/logic/fossil/io/framework.h index 39f5574..5198f4f 100644 --- a/code/logic/fossil/io/framework.h +++ b/code/logic/fossil/io/framework.h @@ -31,7 +31,7 @@ #include "error.h" #include "archive.h" #include "cstring.h" -#include "stream.h" +#include "file.h" #include "soap.h" #include "dir.h" diff --git a/code/logic/meson.build b/code/logic/meson.build index 4f6c4b6..554e92f 100644 --- a/code/logic/meson.build +++ b/code/logic/meson.build @@ -10,7 +10,7 @@ fossil_io_lib = library('fossil_io', 'output.c', 'error.c', 'soap.c', - 'stream.c', + 'file.c', 'dir.c', 'cstring.c' ), From 62e7fc3ac9007c54d04b6480c171e16e23d45067 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:13:41 -0600 Subject: [PATCH 11/21] rename fstream to io_file --- code/logic/file.c | 2 +- code/logic/fossil/io/archive.h | 2 +- code/logic/fossil/io/dir.h | 2 +- code/logic/fossil/io/input.h | 2 +- code/logic/fossil/io/output.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/logic/file.c b/code/logic/file.c index 3cce838..6b75a20 100644 --- a/code/logic/file.c +++ b/code/logic/file.c @@ -22,7 +22,7 @@ * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. * ----------------------------------------------------------------------------- */ -#include "fossil/io/stream.h" +#include "fossil/io/file.h" #include "fossil/io/output.h" #include "fossil/io/error.h" #include diff --git a/code/logic/fossil/io/archive.h b/code/logic/fossil/io/archive.h index 9d8c56d..67e4c25 100644 --- a/code/logic/fossil/io/archive.h +++ b/code/logic/fossil/io/archive.h @@ -25,7 +25,7 @@ #ifndef FOSSIL_IO_ARCHIVE_H #define FOSSIL_IO_ARCHIVE_H -#include "stream.h" +#include "file.h" #ifdef __cplusplus extern "C" { diff --git a/code/logic/fossil/io/dir.h b/code/logic/fossil/io/dir.h index e254c16..c8716bf 100644 --- a/code/logic/fossil/io/dir.h +++ b/code/logic/fossil/io/dir.h @@ -25,7 +25,7 @@ #ifndef FOSSIL_IO_DIR_H #define FOSSIL_IO_DIR_H -#include "stream.h" +#include "file.h" #ifdef __cplusplus extern "C" { diff --git a/code/logic/fossil/io/input.h b/code/logic/fossil/io/input.h index ee9b4c2..3523cc8 100644 --- a/code/logic/fossil/io/input.h +++ b/code/logic/fossil/io/input.h @@ -26,7 +26,7 @@ #define FOSSIL_IO_INPUT_H #include -#include "stream.h" +#include "file.h" /* Contexts */ typedef enum { diff --git a/code/logic/fossil/io/output.h b/code/logic/fossil/io/output.h index e715c3c..1adc379 100644 --- a/code/logic/fossil/io/output.h +++ b/code/logic/fossil/io/output.h @@ -26,7 +26,7 @@ #define FOSSIL_IO_OUTPUT_H #include -#include "stream.h" +#include "file.h" #ifdef __cplusplus extern "C" { From dea5d700d6787b196472ed4617945cad64a17424 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:17:49 -0600 Subject: [PATCH 12/21] this time --- code/logic/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index 48c56c36..a390532 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -29,6 +29,7 @@ #include #include #include +#include // for realpath, getenv, mkdtemp #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -914,7 +915,6 @@ int32_t fossil_io_dir_get_created(const char *path, uint64_t *timestamp){ #ifndef _WIN32 // POSIX does not generally expose creation time; return ctime as approximation stat_t st; - if (stat_native(path, &st) != 0) return -1; #ifdef __APPLE__ *timestamp = (uint64_t)st.st_birthtimespec.tv_sec; #else From 15e61873d5c47b9433535bf6d03f5808dd7631ea Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:20:32 -0600 Subject: [PATCH 13/21] this time --- code/logic/dir.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index a390532..7e5b142 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -30,6 +30,7 @@ #include #include #include // for realpath, getenv, mkdtemp +#include // for mkdtemp #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -915,8 +916,9 @@ int32_t fossil_io_dir_get_created(const char *path, uint64_t *timestamp){ #ifndef _WIN32 // POSIX does not generally expose creation time; return ctime as approximation stat_t st; + if (stat_native(path, &st) != 0) return -1; #ifdef __APPLE__ - *timestamp = (uint64_t)st.st_birthtimespec.tv_sec; + *timestamp = (uint64_t)st.st_birthtime; #else *timestamp = (uint64_t)st.st_ctime; #endif From a05ce5c824c408143c33c4e35a88138eca81344c Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:23:45 -0600 Subject: [PATCH 14/21] using alternitive to mkdtemp in create temp dir --- code/logic/dir.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index 7e5b142..5f06d96 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -882,22 +882,20 @@ int32_t fossil_io_dir_create_temp(char *out, size_t outsz){ if (!out) return -1; char tmpdir[512]; if (fossil_io_dir_temp(tmpdir, sizeof(tmpdir)) != 0) return -1; -#ifdef _WIN32 - char tpl[MAX_PATH]; - snprintf(tpl, sizeof(tpl), "%s\\fossil_tmp_XXXXXX", tmpdir); - // _mktemp_s modifies tpl in-place; create directory - if (_mktemp_s(tpl, sizeof(tpl)) != 0) return -1; - if (_mkdir(tpl) != 0) return -1; - safe_strcpy(out, tpl, outsz); - return 0; -#else + char tpl[PATH_MAX]; - snprintf(tpl, sizeof(tpl), "%s/fossil_tmp_XXXXXX", tmpdir); - char *r = mkdtemp(tpl); - if (!r) return -1; - safe_strcpy(out, r, outsz); - return 0; -#endif + snprintf(tpl, sizeof(tpl), "%s/fossil_tmp_%u_%u", tmpdir, (unsigned)getpid(), (unsigned)time(NULL)); + // Try to create a unique directory by appending a counter + for (int i = 0; i < 1000; ++i) { + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s_%03d", tpl, i); + if (mkdir_native(path, 0700) == 0) { + safe_strcpy(out, path, outsz); + return 0; + } + if (errno != EEXIST) break; + } + return -1; } // ------------------------------------------------------------ From 8f9bf0f4ff109840f06d2b5899fbdd927d1ee151 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:31:59 -0600 Subject: [PATCH 15/21] this time --- code/logic/dir.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index 5f06d96..b92154f 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -252,7 +252,7 @@ static int32_t remove_recursive_internal(const char *path){ do { const char *name = fd.cFileName; if (path_is_dot_or_dotdot(name)) continue; - char child[MAX_PATH]; + char child[PATH_MAX * 2]; snprintf(child, sizeof(child), "%s\\%s", path, name); if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ if (remove_recursive_internal(child) != 0) { FindClose(h); return -1; } @@ -348,7 +348,7 @@ int32_t fossil_io_dir_copy(const char *src, const char *dst){ do { const char *name = fd.cFileName; if (path_is_dot_or_dotdot(name)) continue; - char schild[MAX_PATH], dchild[MAX_PATH]; + char schild[PATH_MAX * 2], dchild[PATH_MAX * 2]; snprintf(schild, sizeof(schild), "%s\\%s", src, name); snprintf(dchild, sizeof(dchild), "%s\\%s", dst, name); if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ @@ -883,11 +883,11 @@ int32_t fossil_io_dir_create_temp(char *out, size_t outsz){ char tmpdir[512]; if (fossil_io_dir_temp(tmpdir, sizeof(tmpdir)) != 0) return -1; - char tpl[PATH_MAX]; + char tpl[PATH_MAX * 2]; snprintf(tpl, sizeof(tpl), "%s/fossil_tmp_%u_%u", tmpdir, (unsigned)getpid(), (unsigned)time(NULL)); // Try to create a unique directory by appending a counter for (int i = 0; i < 1000; ++i) { - char path[PATH_MAX]; + char path[PATH_MAX * 2]; snprintf(path, sizeof(path), "%s_%03d", tpl, i); if (mkdir_native(path, 0700) == 0) { safe_strcpy(out, path, outsz); From 1d768cd79d0dfc88e7b2b09801681a0eda2ca9db Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:39:39 -0600 Subject: [PATCH 16/21] this time --- code/logic/dir.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index b92154f..be85512 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -293,14 +293,14 @@ int32_t fossil_io_dir_clear(const char *path){ return 0; #else WIN32_FIND_DATAA fd; - char search[MAX_PATH]; + char search[PATH_MAX * 2]; snprintf(search, sizeof(search), "%s\\*", path); HANDLE h = FindFirstFileA(search, &fd); if (h == INVALID_HANDLE_VALUE) return -1; do { const char *name = fd.cFileName; if (path_is_dot_or_dotdot(name)) continue; - char child[MAX_PATH]; + char child[PATH_MAX * 2]; snprintf(child, sizeof(child), "%s\\%s", path, name); if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ if (remove_recursive_internal(child) != 0) { FindClose(h); return -1; } @@ -340,7 +340,7 @@ int32_t fossil_io_dir_copy(const char *src, const char *dst){ return rc; #else WIN32_FIND_DATAA fd; - char search[MAX_PATH]; + char search[PATH_MAX * 2]; snprintf(search, sizeof(search), "%s\\*", src); HANDLE h = FindFirstFileA(search, &fd); if (h == INVALID_HANDLE_VALUE) return -1; @@ -387,7 +387,7 @@ static int32_t copy_recursive_internal(const char *src, const char *dst){ return rc; #else WIN32_FIND_DATAA fd; - char search[MAX_PATH]; + char search[PATH_MAX * 2]; snprintf(search, sizeof(search), "%s\\*", src); HANDLE h = FindFirstFileA(search, &fd); if (h == INVALID_HANDLE_VALUE) return -1; @@ -395,7 +395,7 @@ static int32_t copy_recursive_internal(const char *src, const char *dst){ do { const char *name = fd.cFileName; if (path_is_dot_or_dotdot(name)) continue; - char schild[MAX_PATH], dchild[MAX_PATH]; + char schild[PATH_MAX * 2], dchild[PATH_MAX * 2]; snprintf(schild, sizeof(schild), "%s\\%s", src, name); snprintf(dchild, sizeof(dchild), "%s\\%s", dst, name); if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ @@ -696,7 +696,7 @@ int32_t fossil_io_dir_is_empty(const char *path){ return empty; #else WIN32_FIND_DATAA fd; - char search[MAX_PATH]; + char search[PATH_MAX * 2]; snprintf(search, sizeof(search), "%s\\*", path); HANDLE h = FindFirstFileA(search, &fd); if (h == INVALID_HANDLE_VALUE) return -1; @@ -724,7 +724,7 @@ int32_t fossil_io_dir_count(const char *path, size_t *count){ closedir(d); #else WIN32_FIND_DATAA fd; - char search[MAX_PATH]; + char search[PATH_MAX * 2]; snprintf(search, sizeof(search), "%s\\*", path); HANDLE h = FindFirstFileA(search, &fd); if (h == INVALID_HANDLE_VALUE) return -1; @@ -758,14 +758,14 @@ static int32_t size_recursive_internal(const char *path, uint64_t *acc){ return 0; #else WIN32_FIND_DATAA fd; - char search[MAX_PATH]; + char search[PATH_MAX * 2]; snprintf(search, sizeof(search), "%s\\*", path); HANDLE h = FindFirstFileA(search, &fd); if (h == INVALID_HANDLE_VALUE) return -1; do { const char *name = fd.cFileName; if (path_is_dot_or_dotdot(name)) continue; - char child[MAX_PATH]; + char child[PATH_MAX * 2]; snprintf(child, sizeof(child), "%s\\%s", path, name); if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ if (size_recursive_internal(child, acc) != 0) { FindClose(h); return -1; } @@ -880,14 +880,14 @@ int32_t fossil_io_dir_temp(char *out, size_t outsz){ int32_t fossil_io_dir_create_temp(char *out, size_t outsz){ if (!out) return -1; - char tmpdir[512]; + char tmpdir[PATH_MAX * 2]; if (fossil_io_dir_temp(tmpdir, sizeof(tmpdir)) != 0) return -1; - char tpl[PATH_MAX * 2]; + char tpl[PATH_MAX * 4]; snprintf(tpl, sizeof(tpl), "%s/fossil_tmp_%u_%u", tmpdir, (unsigned)getpid(), (unsigned)time(NULL)); // Try to create a unique directory by appending a counter for (int i = 0; i < 1000; ++i) { - char path[PATH_MAX * 2]; + char path[PATH_MAX * 4]; snprintf(path, sizeof(path), "%s_%03d", tpl, i); if (mkdir_native(path, 0700) == 0) { safe_strcpy(out, path, outsz); From 6905c9c0b06b248333e6c8f52eb0f0f553772564 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:43:03 -0600 Subject: [PATCH 17/21] this time --- code/logic/dir.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index be85512..3b22b50 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -670,9 +670,17 @@ int32_t fossil_io_dir_realpath(const char *path, char *out, size_t outsz){ DWORD r = GetFullPathNameA(path, (DWORD)outsz, out, NULL); return (r > 0 && r < outsz) ? 0 : -1; #else - char buf[PATH_MAX]; - if (realpath(path, buf) == NULL) return -1; - safe_strcpy(out, buf, outsz); + // Alternative to realpath: resolve absolute path, but do not resolve symlinks + if (fossil_io_dir_is_absolute(path)) { + safe_strcpy(out, path, outsz); + return 0; + } + char cwd[PATH_MAX]; + if (!getcwd(cwd, sizeof(cwd))) return -1; + char abs[PATH_MAX * 2]; + if (snprintf(abs, sizeof(abs), "%s/%s", cwd, path) >= (int)sizeof(abs)) return -1; + // Normalize the result + fossil_io_dir_normalize(abs, out, outsz); return 0; #endif } From 1e2483805c928d86788b49065396e47a8ff6e485 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:46:06 -0600 Subject: [PATCH 18/21] this time --- code/logic/dir.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index 3b22b50..07d756f 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -525,7 +525,7 @@ int32_t fossil_io_dir_iter_next(fossil_io_dir_iter_t *it){ wh->has_current = 0; // consume current if (!path_is_dot_or_dotdot(name)){ safe_strcpy(it->current.name, name, sizeof(it->current.name)); - snprintf(it->current.path, sizeof(it->current.path), "%s\\%s", it->basepath, name); + fossil_io_dir_join(it->basepath, name, it->current.path, sizeof(it->current.path)); if (wh->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) it->current.type = 1; else it->current.type = 0; // size (DWORD/FILETIME conversion) @@ -895,8 +895,9 @@ int32_t fossil_io_dir_create_temp(char *out, size_t outsz){ snprintf(tpl, sizeof(tpl), "%s/fossil_tmp_%u_%u", tmpdir, (unsigned)getpid(), (unsigned)time(NULL)); // Try to create a unique directory by appending a counter for (int i = 0; i < 1000; ++i) { - char path[PATH_MAX * 4]; - snprintf(path, sizeof(path), "%s_%03d", tpl, i); + char path[PATH_MAX * 4 + 8]; // Extra space for "_%03d" and null terminator + int n = snprintf(path, sizeof(path), "%s_%03d", tpl, i); + if (n < 0 || n >= (int)sizeof(path)) continue; // Skip if truncated if (mkdir_native(path, 0700) == 0) { safe_strcpy(out, path, outsz); return 0; From 10f432fa222a51ab8d7696d57fcaf4d97863901c Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Fri, 21 Nov 2025 18:48:44 -0600 Subject: [PATCH 19/21] this time --- code/logic/dir.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/code/logic/dir.c b/code/logic/dir.c index 07d756f..0b150cf 100644 --- a/code/logic/dir.c +++ b/code/logic/dir.c @@ -69,8 +69,11 @@ static void safe_strcpy(char *dst, const char *src, size_t dstlen){ if (!dst || dstlen == 0) return; if (!src) { dst[0] = '\0'; return; } - strncpy(dst, src, dstlen - 1); - dst[dstlen - 1] = '\0'; + size_t srclen = strlen(src); + if (srclen >= dstlen) + srclen = dstlen - 1; + memcpy(dst, src, srclen); + dst[srclen] = '\0'; } static int32_t join_paths(const char *a, const char *b, char *out, size_t outsz){ @@ -79,17 +82,38 @@ static int32_t join_paths(const char *a, const char *b, char *out, size_t outsz) if (!b || !b[0]) { safe_strcpy(out, a, outsz); return 0; } size_t la = strlen(a); - int need_sep = (a[la-1] != '/' && a[la-1] != '\\'); - + size_t lb = strlen(b); + int need_sep = 0; #ifdef _WIN32 need_sep = (a[la-1] != '\\' && a[la-1] != '/'); +#else + need_sep = (a[la-1] != '/' && a[la-1] != '\\'); #endif - if (need_sep) - snprintf(out, outsz, "%s%c%s", a, PATHSEP, b); - else - snprintf(out, outsz, "%s%s", a, b); - out[outsz-1] = '\0'; + size_t total = la + (need_sep ? 1 : 0) + lb; + if (total >= outsz) { + // Truncate b if needed + size_t copy_b = outsz - la - (need_sep ? 1 : 0) - 1; + if (copy_b > lb) copy_b = lb; + memcpy(out, a, la); + if (need_sep && la < outsz - 1) { + out[la] = PATHSEP; + la++; + } + if (copy_b > 0 && la + copy_b < outsz) { + memcpy(out + la, b, copy_b); + la += copy_b; + } + out[la] = '\0'; + } else { + memcpy(out, a, la); + size_t pos = la; + if (need_sep) { + out[pos++] = PATHSEP; + } + memcpy(out + pos, b, lb); + out[pos + lb] = '\0'; + } return 0; } From 4f70ed371d83b2add73c40a4d70e30509cf99765 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Sat, 22 Nov 2025 18:36:23 -0600 Subject: [PATCH 20/21] add test cases for dir --- code/logic/fossil/io/dir.h | 632 +++++++++++++++++- code/tests/cases/test_dir.c | 293 ++++++++ code/tests/cases/test_dir.cpp | 293 ++++++++ .../cases/{test_stream.c => test_file.c} | 0 .../cases/{test_stream.cpp => test_file.cpp} | 0 5 files changed, 1210 insertions(+), 8 deletions(-) create mode 100644 code/tests/cases/test_dir.c create mode 100644 code/tests/cases/test_dir.cpp rename code/tests/cases/{test_stream.c => test_file.c} (100%) rename code/tests/cases/{test_stream.cpp => test_file.cpp} (100%) diff --git a/code/logic/fossil/io/dir.h b/code/logic/fossil/io/dir.h index c8716bf..dc40e5f 100644 --- a/code/logic/fossil/io/dir.h +++ b/code/logic/fossil/io/dir.h @@ -38,7 +38,7 @@ extern "C" { /** * @brief Represents a directory entry (file, directory, symlink, etc.) */ -typedef struct fossil_io_dir_entry_t { +typedef struct { char name[512]; ///< Entry name char path[1024]; ///< Full resolved path int32_t type; ///< 0=file, 1=dir, 2=symlink, 3=other @@ -54,7 +54,7 @@ typedef struct fossil_io_dir_entry_t { /** * @brief Represents an open directory iterator. */ -typedef struct fossil_io_dir_iter_t { +typedef struct { void *handle; ///< Platform-specific DIR*/HANDLE char basepath[1024]; ///< The directory being iterated fossil_io_dir_entry_t current; @@ -66,16 +66,71 @@ typedef struct fossil_io_dir_iter_t { // Basic Directory Operations // ============================================================================ +/** + * @brief Checks if a directory exists at the given path. + * @param path The directory path to check. + * @return 1 if exists, 0 if not, negative on error. + */ int32_t fossil_io_dir_exists(const char *path); + +/** + * @brief Creates a directory at the specified path. + * @param path The directory path to create. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_create(const char *path); + +/** + * @brief Removes the directory at the specified path. + * @param path The directory path to remove. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_remove(const char *path); + +/** + * @brief Recursively removes a directory and all its contents. + * @param path The directory path to remove. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_remove_recursive(const char *path); + +/** + * @brief Clears all contents of a directory, but does not remove the directory itself. + * @param path The directory path to clear. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_clear(const char *path); +/** + * @brief Copies the contents of one directory to another. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_copy(const char *src, const char *dst); + +/** + * @brief Recursively copies the contents of one directory to another. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_copy_recursive(const char *src, const char *dst); +/** + * @brief Moves a directory from source to destination. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_move(const char *src, const char *dst); + +/** + * @brief Renames a directory from oldpath to newpath. + * @param oldpath The current directory path. + * @param newpath The new directory path. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_rename(const char *oldpath, const char *newpath); @@ -83,10 +138,35 @@ int32_t fossil_io_dir_rename(const char *oldpath, const char *newpath); // Directory Iteration API // ============================================================================ +/** + * @brief Opens a directory iterator for the specified path. + * @param it Pointer to the iterator structure. + * @param path Directory path to iterate. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_iter_open(fossil_io_dir_iter_t *it, const char *path); -int32_t fossil_io_dir_iter_next(fossil_io_dir_iter_t *it); ///< Returns 1 if valid, 0 if end -void fossil_io_dir_iter_close(fossil_io_dir_iter_t *it); +/** + * @brief Advances the iterator to the next directory entry. + * @param it Pointer to the iterator structure. + * @return 1 if valid entry, 0 if end of directory, negative on error. + */ +int32_t fossil_io_dir_iter_next(fossil_io_dir_iter_t *it); + +/** + * @brief Closes the directory iterator and releases resources. + * @param it Pointer to the iterator structure. + */ +void fossil_io_dir_iter_close(fossil_io_dir_iter_t *it); + +/** + * @brief Lists directory entries in the specified path. + * @param path Directory path to list. + * @param entries Array to store directory entries. + * @param count Pointer to store number of entries found. + * @param max_entries Maximum number of entries to list. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_list(const char *path, fossil_io_dir_entry_t *entries, size_t *count, @@ -97,11 +177,57 @@ int32_t fossil_io_dir_list(const char *path, // Path Utilities // ============================================================================ +/** + * @brief Checks if the given path is absolute. + * @param path Path to check. + * @return 1 if absolute, 0 if relative, negative on error. + */ int32_t fossil_io_dir_is_absolute(const char *path); + +/** + * @brief Joins a base path and a name into a single path. + * @param base Base directory path. + * @param name Name to append. + * @param out Output buffer for joined path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_join(const char *base, const char *name, char *out, size_t outsz); + +/** + * @brief Extracts the basename (final component) from a path. + * @param path Input path. + * @param out Output buffer for basename. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_basename(const char *path, char *out, size_t outsz); + +/** + * @brief Extracts the directory name (parent path) from a path. + * @param path Input path. + * @param out Output buffer for dirname. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_dirname(const char *path, char *out, size_t outsz); + +/** + * @brief Normalizes a path, resolving redundant separators and up-level references. + * @param path Input path. + * @param out Output buffer for normalized path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_normalize(const char *path, char *out, size_t outsz); + +/** + * @brief Resolves a path to its absolute, canonical form. + * @param path Input path. + * @param out Output buffer for real path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_realpath(const char *path, char *out, size_t outsz); @@ -109,9 +235,29 @@ int32_t fossil_io_dir_realpath(const char *path, char *out, size_t outsz); // Directory Inspection Queries // ============================================================================ +/** + * @brief Checks if a directory is empty. + * @param path Directory path to check. + * @return 1 if empty, 0 if not, negative on error. + */ int32_t fossil_io_dir_is_empty(const char *path); + +/** + * @brief Counts the number of entries in a directory. + * @param path Directory path to count. + * @param count Pointer to store entry count. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_count(const char *path, size_t *count); -int32_t fossil_io_dir_size(const char *path, uint64_t *bytes); // recursive sum + +/** + * @brief Calculates the total size of a directory (recursive sum). + * @param path Directory path to calculate. + * @param bytes Pointer to store total size in bytes. + * @return 0 on success, negative on error. + */ +int32_t fossil_io_dir_size(const char *path, uint64_t *bytes); + // ============================================================================ // Filtering + Scanning @@ -120,12 +266,30 @@ int32_t fossil_io_dir_size(const char *path, uint64_t *bytes); // recursive sum /** * @brief Callback used for scanning files. * Return 1 to continue, 0 to stop traversal. + * @param entry Pointer to the directory entry. + * @param userdata User-defined data passed to the callback. + * @return 1 to continue, 0 to stop traversal. */ typedef int32_t (*fossil_io_dir_scan_callback)( const fossil_io_dir_entry_t *entry, void *userdata); +/** + * @brief Scans directory entries, invoking a callback for each entry. + * @param path Directory path to scan. + * @param cb Callback function to invoke. + * @param userdata User-defined data passed to callback. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_scan(const char *path, fossil_io_dir_scan_callback cb, void *userdata); + +/** + * @brief Recursively scans directory entries, invoking a callback for each entry. + * @param path Directory path to scan. + * @param cb Callback function to invoke. + * @param userdata User-defined data passed to callback. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_scan_recursive(const char *path, fossil_io_dir_scan_callback cb, void *userdata); @@ -133,7 +297,20 @@ int32_t fossil_io_dir_scan_recursive(const char *path, fossil_io_dir_scan_callba // Permissions (platform supported) // ============================================================================ +/** + * @brief Sets permissions for a directory. + * @param path Directory path. + * @param mode Permission mode to set. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_set_permissions(const char *path, int32_t mode); + +/** + * @brief Gets permissions for a directory. + * @param path Directory path. + * @param mode Pointer to store permission mode. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_get_permissions(const char *path, int32_t *mode); @@ -141,7 +318,20 @@ int32_t fossil_io_dir_get_permissions(const char *path, int32_t *mode); // Temp Directory Utilities // ============================================================================ +/** + * @brief Gets the system temporary directory path. + * @param out Output buffer for temp path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_temp(char *out, size_t outsz); + +/** + * @brief Creates a unique temporary directory. + * @param out Output buffer for temp directory path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_create_temp(char *out, size_t outsz); @@ -149,7 +339,20 @@ int32_t fossil_io_dir_create_temp(char *out, size_t outsz); // Metadata Queries // ============================================================================ +/** + * @brief Gets the last modified timestamp of a directory. + * @param path Directory path. + * @param timestamp Pointer to store modified time (UTC epoch). + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_get_modified(const char *path, uint64_t *timestamp); + +/** + * @brief Gets the creation timestamp of a directory. + * @param path Directory path. + * @param timestamp Pointer to store creation time (UTC epoch). + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_get_created(const char *path, uint64_t *timestamp); @@ -157,8 +360,29 @@ int32_t fossil_io_dir_get_created(const char *path, uint64_t *timestamp); // Directory Sync / Backup // ============================================================================ +/** + * @brief Creates a backup of a directory with the given suffix. + * @param src Source directory path. + * @param suffix Suffix to append to backup directory. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_backup(const char *src, const char *suffix); + +/** + * @brief Mirrors the contents of one directory to another. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_mirror(const char *src, const char *dst); + +/** + * @brief Synchronizes two directories, optionally deleting extraneous files. + * @param src Source directory path. + * @param dst Destination directory path. + * @param delete_extraneous If non-zero, delete files in dst not in src. + * @return 0 on success, negative on error. + */ int32_t fossil_io_dir_sync(const char *src, const char *dst, int32_t delete_extraneous); @@ -166,8 +390,25 @@ int32_t fossil_io_dir_sync(const char *src, const char *dst, int32_t delete_extr // Low-Level Helpers // ============================================================================ +/** + * @brief Checks if the path refers to a directory. + * @param path Path to check. + * @return 1 if directory, 0 if not, negative on error. + */ int32_t fossil_io_dir_is_directory(const char *path); + +/** + * @brief Checks if the path refers to a regular file. + * @param path Path to check. + * @return 1 if file, 0 if not, negative on error. + */ int32_t fossil_io_dir_is_file(const char *path); + +/** + * @brief Checks if the path refers to a symbolic link. + * @param path Path to check. + * @return 1 if symlink, 0 if not, negative on error. + */ int32_t fossil_io_dir_is_symlink(const char *path); #ifdef __cplusplus @@ -184,12 +425,387 @@ namespace fossil { */ namespace io { - + /** + * @brief C++ wrapper for directory operations. + * + * The Dir class provides static methods that wrap the C directory API + * functions, allowing convenient usage from C++ code. It covers basic + * directory management (existence, creation, removal), recursive operations, + * iteration, listing, path utilities, inspection queries, filtering/scanning, + * permissions, temporary directory utilities, metadata queries, sync/backup, + * and low-level helpers for file type checks. + * + * All methods are static and forward their arguments to the corresponding + * C functions, converting std::string to const char* as needed. + */ + class Dir { + public: + /** + * @brief Checks if a directory exists at the given path. + * @param path Directory path to check. + * @return 1 if exists, 0 if not, negative on error. + */ + static int32_t exists(const std::string& path) { + return fossil_io_dir_exists(path.c_str()); + } + + /** + * @brief Creates a directory at the specified path. + * @param path Directory path to create. + * @return 0 on success, negative on error. + */ + static int32_t create(const std::string& path) { + return fossil_io_dir_create(path.c_str()); + } + + /** + * @brief Removes the directory at the specified path. + * @param path Directory path to remove. + * @return 0 on success, negative on error. + */ + static int32_t remove(const std::string& path) { + return fossil_io_dir_remove(path.c_str()); + } + + /** + * @brief Recursively removes a directory and all its contents. + * @param path Directory path to remove. + * @return 0 on success, negative on error. + */ + static int32_t remove_recursive(const std::string& path) { + return fossil_io_dir_remove_recursive(path.c_str()); + } + + /** + * @brief Clears all contents of a directory, but does not remove the directory itself. + * @param path Directory path to clear. + * @return 0 on success, negative on error. + */ + static int32_t clear(const std::string& path) { + return fossil_io_dir_clear(path.c_str()); + } + + /** + * @brief Copies the contents of one directory to another. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ + static int32_t copy(const std::string& src, const std::string& dst) { + return fossil_io_dir_copy(src.c_str(), dst.c_str()); + } + + /** + * @brief Recursively copies the contents of one directory to another. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ + static int32_t copy_recursive(const std::string& src, const std::string& dst) { + return fossil_io_dir_copy_recursive(src.c_str(), dst.c_str()); + } + + /** + * @brief Moves a directory from source to destination. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ + static int32_t move(const std::string& src, const std::string& dst) { + return fossil_io_dir_move(src.c_str(), dst.c_str()); + } + + /** + * @brief Renames a directory from oldpath to newpath. + * @param oldpath Current directory path. + * @param newpath New directory path. + * @return 0 on success, negative on error. + */ + static int32_t rename(const std::string& oldpath, const std::string& newpath) { + return fossil_io_dir_rename(oldpath.c_str(), newpath.c_str()); + } + + /** + * @brief Opens a directory iterator for the specified path. + * @param it Pointer to iterator structure. + * @param path Directory path to iterate. + * @return 0 on success, negative on error. + */ + static int32_t iter_open(fossil_io_dir_iter_t* it, const std::string& path) { + return fossil_io_dir_iter_open(it, path.c_str()); + } + + /** + * @brief Advances the iterator to the next directory entry. + * @param it Pointer to iterator structure. + * @return 1 if valid entry, 0 if end, negative on error. + */ + static int32_t iter_next(fossil_io_dir_iter_t* it) { + return fossil_io_dir_iter_next(it); + } + + /** + * @brief Closes the directory iterator and releases resources. + * @param it Pointer to iterator structure. + */ + static void iter_close(fossil_io_dir_iter_t* it) { + fossil_io_dir_iter_close(it); + } + + /** + * @brief Lists directory entries in the specified path. + * @param path Directory path to list. + * @param entries Array to store directory entries. + * @param count Pointer to store number of entries found. + * @param max_entries Maximum number of entries to list. + * @return 0 on success, negative on error. + */ + static int32_t list(const std::string& path, + fossil_io_dir_entry_t* entries, + size_t* count, + size_t max_entries) { + return fossil_io_dir_list(path.c_str(), entries, count, max_entries); + } + + /** + * @brief Checks if the given path is absolute. + * @param path Path to check. + * @return 1 if absolute, 0 if relative, negative on error. + */ + static int32_t is_absolute(const std::string& path) { + return fossil_io_dir_is_absolute(path.c_str()); + } + + /** + * @brief Joins a base path and a name into a single path. + * @param base Base directory path. + * @param name Name to append. + * @param out Output buffer for joined path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ + static int32_t join(const std::string& base, const std::string& name, char* out, size_t outsz) { + return fossil_io_dir_join(base.c_str(), name.c_str(), out, outsz); + } + + /** + * @brief Extracts the basename (final component) from a path. + * @param path Input path. + * @param out Output buffer for basename. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ + static int32_t basename(const std::string& path, char* out, size_t outsz) { + return fossil_io_dir_basename(path.c_str(), out, outsz); + } + + /** + * @brief Extracts the directory name (parent path) from a path. + * @param path Input path. + * @param out Output buffer for dirname. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ + static int32_t dirname(const std::string& path, char* out, size_t outsz) { + return fossil_io_dir_dirname(path.c_str(), out, outsz); + } + + /** + * @brief Normalizes a path, resolving redundant separators and up-level references. + * @param path Input path. + * @param out Output buffer for normalized path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ + static int32_t normalize(const std::string& path, char* out, size_t outsz) { + return fossil_io_dir_normalize(path.c_str(), out, outsz); + } + + /** + * @brief Resolves a path to its absolute, canonical form. + * @param path Input path. + * @param out Output buffer for real path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ + static int32_t realpath(const std::string& path, char* out, size_t outsz) { + return fossil_io_dir_realpath(path.c_str(), out, outsz); + } + + /** + * @brief Checks if a directory is empty. + * @param path Directory path to check. + * @return 1 if empty, 0 if not, negative on error. + */ + static int32_t is_empty(const std::string& path) { + return fossil_io_dir_is_empty(path.c_str()); + } + + /** + * @brief Counts the number of entries in a directory. + * @param path Directory path to count. + * @param count Pointer to store entry count. + * @return 0 on success, negative on error. + */ + static int32_t count(const std::string& path, size_t* count) { + return fossil_io_dir_count(path.c_str(), count); + } + + /** + * @brief Calculates the total size of a directory (recursive sum). + * @param path Directory path to calculate. + * @param bytes Pointer to store total size in bytes. + * @return 0 on success, negative on error. + */ + static int32_t size(const std::string& path, uint64_t* bytes) { + return fossil_io_dir_size(path.c_str(), bytes); + } + + /** + * @brief Scans directory entries, invoking a callback for each entry. + * @param path Directory path to scan. + * @param cb Callback function to invoke. + * @param userdata User-defined data passed to callback. + * @return 0 on success, negative on error. + */ + static int32_t scan(const std::string& path, fossil_io_dir_scan_callback cb, void* userdata) { + return fossil_io_dir_scan(path.c_str(), cb, userdata); + } + + /** + * @brief Recursively scans directory entries, invoking a callback for each entry. + * @param path Directory path to scan. + * @param cb Callback function to invoke. + * @param userdata User-defined data passed to callback. + * @return 0 on success, negative on error. + */ + static int32_t scan_recursive(const std::string& path, fossil_io_dir_scan_callback cb, void* userdata) { + return fossil_io_dir_scan_recursive(path.c_str(), cb, userdata); + } + + /** + * @brief Sets permissions for a directory. + * @param path Directory path. + * @param mode Permission mode to set. + * @return 0 on success, negative on error. + */ + static int32_t set_permissions(const std::string& path, int32_t mode) { + return fossil_io_dir_set_permissions(path.c_str(), mode); + } + + /** + * @brief Gets permissions for a directory. + * @param path Directory path. + * @param mode Pointer to store permission mode. + * @return 0 on success, negative on error. + */ + static int32_t get_permissions(const std::string& path, int32_t* mode) { + return fossil_io_dir_get_permissions(path.c_str(), mode); + } + + /** + * @brief Gets the system temporary directory path. + * @param out Output buffer for temp path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ + static int32_t temp(char* out, size_t outsz) { + return fossil_io_dir_temp(out, outsz); + } + + /** + * @brief Creates a unique temporary directory. + * @param out Output buffer for temp directory path. + * @param outsz Size of output buffer. + * @return 0 on success, negative on error. + */ + static int32_t create_temp(char* out, size_t outsz) { + return fossil_io_dir_create_temp(out, outsz); + } + + /** + * @brief Gets the last modified timestamp of a directory. + * @param path Directory path. + * @param timestamp Pointer to store modified time (UTC epoch). + * @return 0 on success, negative on error. + */ + static int32_t get_modified(const std::string& path, uint64_t* timestamp) { + return fossil_io_dir_get_modified(path.c_str(), timestamp); + } + + /** + * @brief Gets the creation timestamp of a directory. + * @param path Directory path. + * @param timestamp Pointer to store creation time (UTC epoch). + * @return 0 on success, negative on error. + */ + static int32_t get_created(const std::string& path, uint64_t* timestamp) { + return fossil_io_dir_get_created(path.c_str(), timestamp); + } + + /** + * @brief Creates a backup of a directory with the given suffix. + * @param src Source directory path. + * @param suffix Suffix to append to backup directory. + * @return 0 on success, negative on error. + */ + static int32_t backup(const std::string& src, const std::string& suffix) { + return fossil_io_dir_backup(src.c_str(), suffix.c_str()); + } + + /** + * @brief Mirrors the contents of one directory to another. + * @param src Source directory path. + * @param dst Destination directory path. + * @return 0 on success, negative on error. + */ + static int32_t mirror(const std::string& src, const std::string& dst) { + return fossil_io_dir_mirror(src.c_str(), dst.c_str()); + } + + /** + * @brief Synchronizes two directories, optionally deleting extraneous files. + * @param src Source directory path. + * @param dst Destination directory path. + * @param delete_extraneous If non-zero, delete files in dst not in src. + * @return 0 on success, negative on error. + */ + static int32_t sync(const std::string& src, const std::string& dst, int32_t delete_extraneous) { + return fossil_io_dir_sync(src.c_str(), dst.c_str(), delete_extraneous); + } + + /** + * @brief Checks if the path refers to a directory. + * @param path Path to check. + * @return 1 if directory, 0 if not, negative on error. + */ + static int32_t is_directory(const std::string& path) { + return fossil_io_dir_is_directory(path.c_str()); + } + + /** + * @brief Checks if the path refers to a regular file. + * @param path Path to check. + * @return 1 if file, 0 if not, negative on error. + */ + static int32_t is_file(const std::string& path) { + return fossil_io_dir_is_file(path.c_str()); + } + + /** + * @brief Checks if the path refers to a symbolic link. + * @param path Path to check. + * @return 1 if symlink, 0 if not, negative on error. + */ + static int32_t is_symlink(const std::string& path) { + return fossil_io_dir_is_symlink(path.c_str()); + } + }; } } -#endif +#endif /* __cplusplus */ -#endif /* FOSSIL_IO_FRAMEWORK_H */ +#endif /* FOSSIL_IO_DIR_H */ diff --git a/code/tests/cases/test_dir.c b/code/tests/cases/test_dir.c new file mode 100644 index 0000000..db1c18e --- /dev/null +++ b/code/tests/cases/test_dir.c @@ -0,0 +1,293 @@ +/** + * ----------------------------------------------------------------------------- + * Project: Fossil Logic + * + * This file is part of the Fossil Logic project, which aims to develop + * high-performance, cross-platform applications and libraries. The code + * contained herein is licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain + * a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Author: Michael Gene Brockus (Dreamer) + * Date: 04/05/2014 + * + * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. + * ----------------------------------------------------------------------------- + */ +#include + +#include "fossil/io/framework.h" + + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Utilites +// * * * * * * * * * * * * * * * * * * * * * * * * +// Setup steps for things like test fixtures and +// mock objects are set here. +// * * * * * * * * * * * * * * * * * * * * * * * * + +// Define the test suite and add test cases +FOSSIL_SUITE(c_dir_suite); + +// Setup function for the test suite +FOSSIL_SETUP(c_dir_suite) { + // Setup code here +} + +// Teardown function for the test suite +FOSSIL_TEARDOWN(c_dir_suite) { + // Teardown code here +} + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Cases +// * * * * * * * * * * * * * * * * * * * * * * * * +// The test cases below are provided as samples, inspired +// by the Meson build system's approach of using test cases +// as samples for library usage. +// * * * * * * * * * * * * * * * * * * * * * * * * + +FOSSIL_TEST(c_test_dir_create_and_exists) { + const char *dirname = "test_dir_create"; + // Ensure directory does not exist + fossil_io_dir_remove_recursive(dirname); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_exists(dirname)); + // Create directory + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_create(dirname)); + // Check existence + ASSUME_ITS_EQUAL_I32(1, fossil_io_dir_exists(dirname)); + // Cleanup + fossil_io_dir_remove_recursive(dirname); +} + +FOSSIL_TEST(c_test_dir_remove_and_remove_recursive) { + const char *dirname = "test_dir_remove"; + fossil_io_dir_remove_recursive(dirname); + fossil_io_dir_create(dirname); + // Remove directory + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_remove(dirname)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_exists(dirname)); + // Create nested structure + fossil_io_dir_create(dirname); + char subdir[128]; + fossil_io_dir_join(dirname, "sub", subdir, sizeof(subdir)); + fossil_io_dir_create(subdir); + // Remove recursively + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_remove_recursive(dirname)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_exists(dirname)); +} + +FOSSIL_TEST(c_test_dir_clear) { + const char *dirname = "test_dir_clear"; + fossil_io_dir_remove_recursive(dirname); + fossil_io_dir_create(dirname); + char fname[128]; + fossil_io_dir_join(dirname, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "data"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_clear(dirname)); + size_t count = 0; + fossil_io_dir_count(dirname, &count); + ASSUME_ITS_EQUAL_I32(0, count); + fossil_io_dir_remove_recursive(dirname); +} + +FOSSIL_TEST(c_test_dir_copy_and_copy_recursive) { + const char *src = "test_dir_src"; + const char *dst = "test_dir_dst"; + fossil_io_dir_remove_recursive(src); + fossil_io_dir_remove_recursive(dst); + fossil_io_dir_create(src); + char fname[128]; + fossil_io_dir_join(src, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "copytest"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_copy(src, dst)); + size_t count = 0; + fossil_io_dir_count(dst, &count); + ASSUME_ITS_TRUE(count > 0); + fossil_io_dir_remove_recursive(src); + fossil_io_dir_remove_recursive(dst); +} + +FOSSIL_TEST(c_test_dir_move_and_rename) { + const char *src = "test_dir_move_src"; + const char *dst = "test_dir_move_dst"; + fossil_io_dir_remove_recursive(src); + fossil_io_dir_remove_recursive(dst); + fossil_io_dir_create(src); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_move(src, dst)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_dir_exists(dst)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_exists(src)); + const char *renamed = "test_dir_renamed"; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_rename(dst, renamed)); + ASSUME_ITS_EQUAL_I32(1, fossil_io_dir_exists(renamed)); + fossil_io_dir_remove_recursive(renamed); +} + +FOSSIL_TEST(c_test_dir_iter_and_list) { + const char *dirname = "test_dir_iter"; + fossil_io_dir_remove_recursive(dirname); + fossil_io_dir_create(dirname); + + // Create a file in the directory + char fname[128]; + fossil_io_dir_join(dirname, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "entry"); + fclose(f); + + // Test directory iterator + fossil_io_dir_iter_t it; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_iter_open(&it, dirname)); + int found = 0; + while (fossil_io_dir_iter_next(&it)) { + // Check if the entry is "file.txt" + if (strcmp(it.current.name, "file.txt") == 0) { + found = 1; + // Optionally, check entry fields + ASSUME_ITS_EQUAL_I32(0, it.current.type); // 0=file + ASSUME_ITS_TRUE(it.current.size > 0); + ASSUME_ITS_TRUE(strlen(it.current.path) > 0); + } + } + fossil_io_dir_iter_close(&it); + ASSUME_ITS_TRUE(found); + + // Test directory listing + fossil_io_dir_entry_t entries[10]; + size_t count = 0; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_list(dirname, entries, &count, 10)); + ASSUME_ITS_TRUE(count > 0); + int listed = 0; + for (size_t i = 0; i < count; ++i) { + if (strcmp(entries[i].name, "file.txt") == 0) { + listed = 1; + ASSUME_ITS_EQUAL_I32(0, entries[i].type); // 0=file + ASSUME_ITS_TRUE(entries[i].size > 0); + ASSUME_ITS_TRUE(strlen(entries[i].path) > 0); + } + } + ASSUME_ITS_TRUE(listed); + + fossil_io_dir_remove_recursive(dirname); +} + +FOSSIL_TEST(c_test_dir_path_utilities) { + char out[256]; + ASSUME_ITS_EQUAL_I32(1, fossil_io_dir_is_absolute("/tmp")); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_is_absolute("relative/path")); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_join("/tmp", "file.txt", out, sizeof(out))); + ASSUME_ITS_TRUE(strstr(out, "file.txt") != NULL); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_basename("/tmp/file.txt", out, sizeof(out))); + ASSUME_ITS_EQUAL_CSTR("file.txt", out); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_dirname("/tmp/file.txt", out, sizeof(out))); + ASSUME_ITS_TRUE(strstr(out, "/tmp") != NULL); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_normalize("/tmp//foo/", out, sizeof(out))); + ASSUME_ITS_TRUE(strstr(out, "/tmp/foo") != NULL); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_realpath(".", out, sizeof(out))); + ASSUME_ITS_TRUE(strlen(out) > 0); +} + +FOSSIL_TEST(c_test_dir_is_empty_and_count_and_size) { + const char *dirname = "test_dir_empty"; + fossil_io_dir_remove_recursive(dirname); + fossil_io_dir_create(dirname); + ASSUME_ITS_EQUAL_I32(1, fossil_io_dir_is_empty(dirname)); + char fname[128]; + fossil_io_dir_join(dirname, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "abc"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_is_empty(dirname)); + size_t count = 0; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_count(dirname, &count)); + ASSUME_ITS_EQUAL_I32(1, count); + uint64_t bytes = 0; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_size(dirname, &bytes)); + ASSUME_ITS_TRUE(bytes > 0); + fossil_io_dir_remove_recursive(dirname); +} + +FOSSIL_TEST(c_test_dir_permissions) { + const char *dirname = "test_dir_perm"; + fossil_io_dir_remove_recursive(dirname); + fossil_io_dir_create(dirname); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_set_permissions(dirname, 0755)); + int32_t mode = 0; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_get_permissions(dirname, &mode)); + ASSUME_ITS_TRUE(mode != 0); + fossil_io_dir_remove_recursive(dirname); +} + +FOSSIL_TEST(c_test_dir_temp_and_create_temp) { + char tempdir[256]; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_temp(tempdir, sizeof(tempdir))); + ASSUME_ITS_TRUE(strlen(tempdir) > 0); + char tempcreated[256]; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_create_temp(tempcreated, sizeof(tempcreated))); + ASSUME_ITS_TRUE(fossil_io_dir_exists(tempcreated)); + fossil_io_dir_remove_recursive(tempcreated); +} + +FOSSIL_TEST(c_test_dir_metadata) { + const char *dirname = "test_dir_meta"; + fossil_io_dir_remove_recursive(dirname); + fossil_io_dir_create(dirname); + uint64_t mod = 0, created = 0; + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_get_modified(dirname, &mod)); + ASSUME_ITS_TRUE(mod > 0); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_get_created(dirname, &created)); + ASSUME_ITS_TRUE(created > 0); + fossil_io_dir_remove_recursive(dirname); +} + +FOSSIL_TEST(c_test_dir_backup_mirror_sync) { + const char *src = "test_dir_sync_src"; + const char *dst = "test_dir_sync_dst"; + fossil_io_dir_remove_recursive(src); + fossil_io_dir_remove_recursive(dst); + fossil_io_dir_create(src); + char fname[128]; + fossil_io_dir_join(src, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "sync"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_backup(src, "_bak")); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_mirror(src, dst)); + ASSUME_ITS_EQUAL_I32(0, fossil_io_dir_sync(src, dst, 1)); + fossil_io_dir_remove_recursive(src); + fossil_io_dir_remove_recursive(dst); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Pool +// * * * * * * * * * * * * * * * * * * * * * * * * + +FOSSIL_TEST_GROUP(c_dir_tests) { + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_create_and_exists); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_remove_and_remove_recursive); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_clear); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_copy_and_copy_recursive); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_move_and_rename); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_iter_and_list); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_path_utilities); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_is_empty_and_count_and_size); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_permissions); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_temp_and_create_temp); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_metadata); + FOSSIL_TEST_ADD(c_dir_suite, c_test_dir_backup_mirror_sync); + + FOSSIL_TEST_REGISTER(c_dir_suite); +} diff --git a/code/tests/cases/test_dir.cpp b/code/tests/cases/test_dir.cpp new file mode 100644 index 0000000..6482034 --- /dev/null +++ b/code/tests/cases/test_dir.cpp @@ -0,0 +1,293 @@ +/** + * ----------------------------------------------------------------------------- + * Project: Fossil Logic + * + * This file is part of the Fossil Logic project, which aims to develop + * high-performance, cross-platform applications and libraries. The code + * contained herein is licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain + * a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Author: Michael Gene Brockus (Dreamer) + * Date: 04/05/2014 + * + * Copyright (C) 2014-2025 Fossil Logic. All rights reserved. + * ----------------------------------------------------------------------------- + */ +#include + +#include "fossil/io/framework.h" + + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Utilites +// * * * * * * * * * * * * * * * * * * * * * * * * +// Setup steps for things like test fixtures and +// mock objects are set here. +// * * * * * * * * * * * * * * * * * * * * * * * * + +// Define the test suite and add test cases +FOSSIL_SUITE(cpp_dir_suite); + +// Setup function for the test suite +FOSSIL_SETUP(cpp_dir_suite) { + // Setup code here +} + +// Teardown function for the test suite +FOSSIL_TEARDOWN(cpp_dir_suite) { + // Teardown code here +} + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Cases +// * * * * * * * * * * * * * * * * * * * * * * * * +// The test cases below are provided as samples, inspired +// by the Meson build system's approach of using test cases +// as samples for library usage. +// * * * * * * * * * * * * * * * * * * * * * * * * + +FOSSIL_TEST(cpp_test_dir_create_and_exists) { + using fossil::io::Dir; + const std::string dirname = "test_dir_create"; + Dir::remove_recursive(dirname); + ASSUME_ITS_EQUAL_I32(0, Dir::exists(dirname)); + ASSUME_ITS_EQUAL_I32(0, Dir::create(dirname)); + ASSUME_ITS_EQUAL_I32(1, Dir::exists(dirname)); + Dir::remove_recursive(dirname); +} + +FOSSIL_TEST(cpp_test_dir_remove_and_remove_recursive) { + using fossil::io::Dir; + const std::string dirname = "test_dir_remove"; + Dir::remove_recursive(dirname); + Dir::create(dirname); + ASSUME_ITS_EQUAL_I32(0, Dir::remove(dirname)); + ASSUME_ITS_EQUAL_I32(0, Dir::exists(dirname)); + Dir::create(dirname); + char subdir[128]; + Dir::join(dirname, "sub", subdir, sizeof(subdir)); + Dir::create(subdir); + ASSUME_ITS_EQUAL_I32(0, Dir::remove_recursive(dirname)); + ASSUME_ITS_EQUAL_I32(0, Dir::exists(dirname)); +} + +FOSSIL_TEST(cpp_test_dir_clear) { + using fossil::io::Dir; + const std::string dirname = "test_dir_clear"; + Dir::remove_recursive(dirname); + Dir::create(dirname); + char fname[128]; + Dir::join(dirname, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "data"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, Dir::clear(dirname)); + size_t count = 0; + Dir::count(dirname, &count); + ASSUME_ITS_EQUAL_I32(0, count); + Dir::remove_recursive(dirname); +} + +FOSSIL_TEST(cpp_test_dir_copy_and_copy_recursive) { + using fossil::io::Dir; + const std::string src = "test_dir_src"; + const std::string dst = "test_dir_dst"; + Dir::remove_recursive(src); + Dir::remove_recursive(dst); + Dir::create(src); + char fname[128]; + Dir::join(src, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "copytest"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, Dir::copy(src, dst)); + size_t count = 0; + Dir::count(dst, &count); + ASSUME_ITS_TRUE(count > 0); + Dir::remove_recursive(src); + Dir::remove_recursive(dst); +} + +FOSSIL_TEST(cpp_test_dir_move_and_rename) { + using fossil::io::Dir; + const std::string src = "test_dir_move_src"; + const std::string dst = "test_dir_move_dst"; + Dir::remove_recursive(src); + Dir::remove_recursive(dst); + Dir::create(src); + ASSUME_ITS_EQUAL_I32(0, Dir::move(src, dst)); + ASSUME_ITS_EQUAL_I32(1, Dir::exists(dst)); + ASSUME_ITS_EQUAL_I32(0, Dir::exists(src)); + const std::string renamed = "test_dir_renamed"; + ASSUME_ITS_EQUAL_I32(0, Dir::rename(dst, renamed)); + ASSUME_ITS_EQUAL_I32(1, Dir::exists(renamed)); + Dir::remove_recursive(renamed); +} + +FOSSIL_TEST(cpp_test_dir_iter_and_list) { + using fossil::io::Dir; + const std::string dirname = "test_dir_iter"; + Dir::remove_recursive(dirname); + Dir::create(dirname); + + char fname[128]; + Dir::join(dirname, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "entry"); + fclose(f); + + fossil_io_dir_iter_t it; + ASSUME_ITS_EQUAL_I32(0, Dir::iter_open(&it, dirname)); + int found = 0; + while (Dir::iter_next(&it)) { + if (strcmp(it.current.name, "file.txt") == 0) { + found = 1; + ASSUME_ITS_EQUAL_I32(0, it.current.type); + ASSUME_ITS_TRUE(it.current.size > 0); + ASSUME_ITS_TRUE(strlen(it.current.path) > 0); + } + } + Dir::iter_close(&it); + ASSUME_ITS_TRUE(found); + + fossil_io_dir_entry_t entries[10]; + size_t count = 0; + ASSUME_ITS_EQUAL_I32(0, Dir::list(dirname, entries, &count, 10)); + ASSUME_ITS_TRUE(count > 0); + int listed = 0; + for (size_t i = 0; i < count; ++i) { + if (strcmp(entries[i].name, "file.txt") == 0) { + listed = 1; + ASSUME_ITS_EQUAL_I32(0, entries[i].type); + ASSUME_ITS_TRUE(entries[i].size > 0); + ASSUME_ITS_TRUE(strlen(entries[i].path) > 0); + } + } + ASSUME_ITS_TRUE(listed); + + Dir::remove_recursive(dirname); +} + +FOSSIL_TEST(cpp_test_dir_path_utilities) { + using fossil::io::Dir; + char out[256]; + ASSUME_ITS_EQUAL_I32(1, Dir::is_absolute("/tmp")); + ASSUME_ITS_EQUAL_I32(0, Dir::is_absolute("relative/path")); + ASSUME_ITS_EQUAL_I32(0, Dir::join("/tmp", "file.txt", out, sizeof(out))); + ASSUME_ITS_TRUE(strstr(out, "file.txt") != NULL); + ASSUME_ITS_EQUAL_I32(0, Dir::basename("/tmp/file.txt", out, sizeof(out))); + ASSUME_ITS_EQUAL_CSTR("file.txt", out); + ASSUME_ITS_EQUAL_I32(0, Dir::dirname("/tmp/file.txt", out, sizeof(out))); + ASSUME_ITS_TRUE(strstr(out, "/tmp") != NULL); + ASSUME_ITS_EQUAL_I32(0, Dir::normalize("/tmp//foo/", out, sizeof(out))); + ASSUME_ITS_TRUE(strstr(out, "/tmp/foo") != NULL); + ASSUME_ITS_EQUAL_I32(0, Dir::realpath(".", out, sizeof(out))); + ASSUME_ITS_TRUE(strlen(out) > 0); +} + +FOSSIL_TEST(cpp_test_dir_is_empty_and_count_and_size) { + using fossil::io::Dir; + const std::string dirname = "test_dir_empty"; + Dir::remove_recursive(dirname); + Dir::create(dirname); + ASSUME_ITS_EQUAL_I32(1, Dir::is_empty(dirname)); + char fname[128]; + Dir::join(dirname, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "abc"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, Dir::is_empty(dirname)); + size_t count = 0; + ASSUME_ITS_EQUAL_I32(0, Dir::count(dirname, &count)); + ASSUME_ITS_EQUAL_I32(1, count); + uint64_t bytes = 0; + ASSUME_ITS_EQUAL_I32(0, Dir::size(dirname, &bytes)); + ASSUME_ITS_TRUE(bytes > 0); + Dir::remove_recursive(dirname); +} + +FOSSIL_TEST(cpp_test_dir_permissions) { + using fossil::io::Dir; + const std::string dirname = "test_dir_perm"; + Dir::remove_recursive(dirname); + Dir::create(dirname); + ASSUME_ITS_EQUAL_I32(0, Dir::set_permissions(dirname, 0755)); + int32_t mode = 0; + ASSUME_ITS_EQUAL_I32(0, Dir::get_permissions(dirname, &mode)); + ASSUME_ITS_TRUE(mode != 0); + Dir::remove_recursive(dirname); +} + +FOSSIL_TEST(cpp_test_dir_temp_and_create_temp) { + using fossil::io::Dir; + char tempdir[256]; + ASSUME_ITS_EQUAL_I32(0, Dir::temp(tempdir, sizeof(tempdir))); + ASSUME_ITS_TRUE(strlen(tempdir) > 0); + char tempcreated[256]; + ASSUME_ITS_EQUAL_I32(0, Dir::create_temp(tempcreated, sizeof(tempcreated))); + ASSUME_ITS_TRUE(Dir::exists(tempcreated)); + Dir::remove_recursive(tempcreated); +} + +FOSSIL_TEST(cpp_test_dir_metadata) { + using fossil::io::Dir; + const std::string dirname = "test_dir_meta"; + Dir::remove_recursive(dirname); + Dir::create(dirname); + uint64_t mod = 0, created = 0; + ASSUME_ITS_EQUAL_I32(0, Dir::get_modified(dirname, &mod)); + ASSUME_ITS_TRUE(mod > 0); + ASSUME_ITS_EQUAL_I32(0, Dir::get_created(dirname, &created)); + ASSUME_ITS_TRUE(created > 0); + Dir::remove_recursive(dirname); +} + +FOSSIL_TEST(cpp_test_dir_backup_mirror_sync) { + using fossil::io::Dir; + const std::string src = "test_dir_syncpp_src"; + const std::string dst = "test_dir_syncpp_dst"; + Dir::remove_recursive(src); + Dir::remove_recursive(dst); + Dir::create(src); + char fname[128]; + Dir::join(src, "file.txt", fname, sizeof(fname)); + FILE *f = fopen(fname, "w"); + fprintf(f, "sync"); + fclose(f); + ASSUME_ITS_EQUAL_I32(0, Dir::backup(src, "_bak")); + ASSUME_ITS_EQUAL_I32(0, Dir::mirror(src, dst)); + ASSUME_ITS_EQUAL_I32(0, Dir::sync(src, dst, 1)); + Dir::remove_recursive(src); + Dir::remove_recursive(dst); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Pool +// * * * * * * * * * * * * * * * * * * * * * * * * + +FOSSIL_TEST_GROUP(cpp_dir_tests) { + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_create_and_exists); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_remove_and_remove_recursive); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_clear); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_copy_and_copy_recursive); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_move_and_rename); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_iter_and_list); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_path_utilities); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_is_empty_and_count_and_size); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_permissions); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_temp_and_create_temp); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_metadata); + FOSSIL_TEST_ADD(cpp_dir_suite, cpp_test_dir_backup_mirror_sync); + + FOSSIL_TEST_REGISTER(cpp_dir_suite); +} diff --git a/code/tests/cases/test_stream.c b/code/tests/cases/test_file.c similarity index 100% rename from code/tests/cases/test_stream.c rename to code/tests/cases/test_file.c diff --git a/code/tests/cases/test_stream.cpp b/code/tests/cases/test_file.cpp similarity index 100% rename from code/tests/cases/test_stream.cpp rename to code/tests/cases/test_file.cpp From c1bc43b3a16877f2409a43f155a22605089fbbe5 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" Date: Sat, 22 Nov 2025 18:47:43 -0600 Subject: [PATCH 21/21] 0.2.5 to 0.2.6 --- README.md | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c3cb05e..3df5ccd 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Add the `fossil-io.wrap` file in your `subprojects` directory and include the fo ```ini [wrap-git] url = https://github.com/fossillogic/fossil-io.git -revision = v0.2.4 +revision = v0.2.6 [provide] dependency_names = fossil-io diff --git a/meson.build b/meson.build index 0c9d09b..2c75b39 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project('Fossil Io', 'c', 'cpp', meson_version: '>=1.8.0', license: 'Apache-2.0', - version: '0.2.5', + version: '0.2.6', default_options: [ 'c_std=c11,c18', 'cpp_std=c++20',