diff --git a/io-test/io-units.c b/io-test/io-units.c new file mode 100644 index 0000000..750eeda --- /dev/null +++ b/io-test/io-units.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +void test_path_1(CuTest *tc) +{ + b_path *path = b_path_create_from_cstr("C:\\hello\\world\\"); + char buf[512]; + b_stringstream str; + b_stringstream_begin(&str, buf, sizeof buf); + + b_to_string(B_OBJECT(path), &str); + + printf("%s\n", buf); + + b_path *path2 = b_path_create_from_cstr("path1\\path2\\"); + b_path *path3 = b_path_create_from_cstr("path3\\path4\\"); + + b_path *paths[] = {path, path2, path3}; + + b_path *path4 = b_path_join(paths, sizeof paths / sizeof *paths); + + b_stringstream_begin(&str, buf, sizeof buf); + b_to_string(B_OBJECT(path4), &str); + printf("%s\n", buf); +} + +CuSuite *get_all_tests(void) +{ + CuSuite *suite = CuSuiteNew(); + + SUITE_ADD_TEST(suite, test_path_1); + + return suite; +} diff --git a/io/CMakeLists.txt b/io/CMakeLists.txt index fd25714..7887d12 100644 --- a/io/CMakeLists.txt +++ b/io/CMakeLists.txt @@ -1,3 +1,3 @@ include(../cmake/Templates.cmake) -add_bluelib_module(NAME io DEPENDENCIES core) +add_bluelib_module(NAME io DEPENDENCIES core object) diff --git a/io/include/blue/io/path.h b/io/include/blue/io/path.h index 30590d2..03b6d2d 100644 --- a/io/include/blue/io/path.h +++ b/io/include/blue/io/path.h @@ -8,16 +8,21 @@ typedef struct b_path b_path; -BLUE_API b_status b_path_create(b_path **out); -BLUE_API b_status b_path_create_root(b_path **out); -BLUE_API b_status b_path_create_cwd(b_path **out); -BLUE_API b_status b_path_create_from_cstr(const char *path, b_path **out); +BLUE_API b_path *b_path_create(); +BLUE_API b_path *b_path_create_root(); +BLUE_API b_path *b_path_create_cwd(); +BLUE_API b_path *b_path_create_from_cstr(const char *path); -BLUE_API b_status b_path_join(const b_path *paths[], size_t nr_paths, b_path **out); +BLUE_API b_path *b_path_join(const b_path *paths[], size_t nr_paths); -BLUE_API b_status b_path_make_absolute(const b_path *in, b_path **out); -BLUE_API b_status b_path_make_relative(const b_path *in, b_path **out); -BLUE_API b_status b_path_make_canonical(const b_path *in, b_path **out); +BLUE_API b_path *b_path_make_absolute(const b_path *in); +BLUE_API b_path *b_path_make_relative(const b_path *in); +BLUE_API b_path *b_path_make_canonical(const b_path *in); + +BLUE_API bool b_path_is_absolute(const b_path *path); +BLUE_API bool b_path_exists(const b_path *path); +BLUE_API bool b_path_is_file(const b_path *path); +BLUE_API bool b_path_is_directory(const b_path *path); BLUE_API b_path *b_path_retain(b_path *path); BLUE_API void b_path_release(b_path *path); diff --git a/io/sys/windows/directory.c b/io/sys/windows/directory.c new file mode 100644 index 0000000..c9b491f --- /dev/null +++ b/io/sys/windows/directory.c @@ -0,0 +1,36 @@ +#include + +struct b_directory { + char *abs_path; +}; + +struct z__b_directory_iterator { + int x; +}; + +enum b_status b_directory_open( + struct b_directory *root, const char *path, struct b_directory **out) +{ + return B_SUCCESS; +} + +int b_directory_iterator_begin( + struct b_directory *directory, struct b_directory_iterator *it) +{ + return 0; +} + +bool b_directory_iterator_next(struct b_directory_iterator *it) +{ + return false; +} + +enum b_status b_directory_iterator_erase(struct b_directory_iterator *it) +{ + return B_SUCCESS; +} + +bool b_directory_iterator_is_valid(const struct b_directory_iterator *it) +{ + return false; +} diff --git a/io/sys/windows/path.c b/io/sys/windows/path.c new file mode 100644 index 0000000..08e0e63 --- /dev/null +++ b/io/sys/windows/path.c @@ -0,0 +1,234 @@ +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include +#include +#include + +struct b_path { + struct b_object base; + struct b_string *pathstr; +}; + +static void path_release(struct b_object *obj); +static void path_to_string(struct b_object *obj, struct b_stringstream *out); + +static struct b_object_type path_type = { + .t_name = "corelib::path", + .t_flags = B_OBJECT_FUNDAMENTAL, + .t_id = B_OBJECT_TYPE_PATH, + .t_instance_size = sizeof(struct b_path), + .t_release = path_release, + .t_to_string = path_to_string, +}; + +struct b_path *b_path_create() +{ + struct b_path *path + = (struct b_path *)b_object_type_instantiate(&path_type); + if (!path) { + return NULL; + } + + path->pathstr = b_string_create(); + if (!path->pathstr) { + b_path_release(path); + return NULL; + } + + return path; +} + +struct b_path *b_path_create_root() +{ + const char *system_drive = getenv("SystemDrive"); + if (!system_drive) { + /* take an educated guess. */ + system_drive = "C:"; + } + + size_t system_drive_len = strlen(system_drive); + + struct b_path *path = b_path_create(); + if (!path) { + return NULL; + } + + b_string_append_cstr(path->pathstr, system_drive); + if (system_drive[system_drive_len - 1] != '\\') { + b_string_append_cstr(path->pathstr, "\\"); + } + + return path; +} + +struct b_path *b_path_create_cwd() +{ + DWORD cwd_len = GetCurrentDirectory(0, NULL); + if (cwd_len == 0) { + return NULL; + } + + TCHAR *cwd_buf = malloc(cwd_len + 1); + if (!cwd_buf) { + return NULL; + } + + cwd_len = GetCurrentDirectory(cwd_len + 1, cwd_buf); + if (cwd_len == 0) { + free(cwd_buf); + return NULL; + } + + struct b_path *path = b_path_create(); + if (!path) { + return NULL; + } + + for (DWORD i = 0; i < cwd_len; i++) { + TCHAR c = cwd_buf[i]; + char s[] = {(c >= 128 ? '?' : (char)c), 0}; + b_string_append_cstr(path->pathstr, s); + } + + free(cwd_buf); + return path; +} + +struct b_path *b_path_create_from_cstr(const char *cstr) +{ + struct b_path *path = b_path_create(); + if (!path) { + return NULL; + } + + char prev = 0; + + for (size_t i = 0; cstr[i]; i++) { + char c = cstr[i]; + if (c == '\\') { + c = '/'; + } + + if (prev == '/' && c == '/') { + continue; + } + + + char s[] = {c, 0}; + b_string_append_cstr(path->pathstr, s); + prev = c; + } + + while (b_string_back(path->pathstr) == '/') { + b_string_pop_back(path->pathstr); + } + + return path; +} + +static void append_path(struct b_path *dest, const struct b_path *src) +{ + if (b_path_is_absolute(src)) { + b_string_clear(dest->pathstr); + b_string_append_s(dest->pathstr, src->pathstr); + return; + } + + if (b_string_back(dest->pathstr) != '/' + && b_string_front(src->pathstr) != '/') { + char s[] = {'/', 0}; + b_string_append_cstr(dest->pathstr, s); + } + + b_string_append_s(dest->pathstr, src->pathstr); +} + +struct b_path *b_path_join( + const b_path *paths[], size_t nr_paths) +{ + struct b_path *result = b_path_create(); + if (!result) { + return NULL; + } + + for (size_t i = 0; i < nr_paths; i++) { + append_path(result, paths[i]); + } + + return result; +} + +struct b_path *b_path_make_absolute(const struct b_path *in) +{ +} + +struct b_path *b_path_make_relative(const struct b_path *in) +{ +} + +struct b_path *b_path_make_canonical(const struct b_path *in) +{ +} + +bool b_path_is_absolute(const struct b_path *path) +{ + const char *s = b_string_ptr(path->pathstr); + + size_t i; + for (i = 0; s[i]; i++) { + char c = s[i]; + + if (!isalpha(c)) { + break; + } + } + + if (s[i++] != ':') { + return false; + } + + if (s[i++] != '/') { + return false; + } + + return true; +} + +bool b_path_exists(const struct b_path *path) +{ + +} + +bool b_path_is_file(const struct b_path *path) +{ + +} + +bool b_path_is_directory(const struct b_path *path) +{ + +} + +struct b_path *b_path_retain(struct b_path *path) +{ +} + +void b_path_release(struct b_path *path) +{ +} + +void path_release(struct b_object* obj) +{ + b_path_release((struct b_path *)obj); +} + +void path_to_string(struct b_object* obj, struct b_stringstream* out) +{ + struct b_path *path = (struct b_path *)obj; + + b_stringstream_add(out, b_string_ptr(path->pathstr)); +} \ No newline at end of file