io: implement path manipulation on windows
This commit is contained in:
36
io-test/io-units.c
Normal file
36
io-test/io-units.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include <CuTest.h>
|
||||||
|
#include <blue/io/path.h>
|
||||||
|
#include <blue/object/object.h>
|
||||||
|
#include <blue/core/stringstream.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
include(../cmake/Templates.cmake)
|
include(../cmake/Templates.cmake)
|
||||||
|
|
||||||
add_bluelib_module(NAME io DEPENDENCIES core)
|
add_bluelib_module(NAME io DEPENDENCIES core object)
|
||||||
|
|||||||
@@ -8,16 +8,21 @@
|
|||||||
|
|
||||||
typedef struct b_path b_path;
|
typedef struct b_path b_path;
|
||||||
|
|
||||||
BLUE_API b_status b_path_create(b_path **out);
|
BLUE_API b_path *b_path_create();
|
||||||
BLUE_API b_status b_path_create_root(b_path **out);
|
BLUE_API b_path *b_path_create_root();
|
||||||
BLUE_API b_status b_path_create_cwd(b_path **out);
|
BLUE_API b_path *b_path_create_cwd();
|
||||||
BLUE_API b_status b_path_create_from_cstr(const char *path, b_path **out);
|
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_path *b_path_make_absolute(const b_path *in);
|
||||||
BLUE_API b_status b_path_make_relative(const b_path *in, b_path **out);
|
BLUE_API b_path *b_path_make_relative(const b_path *in);
|
||||||
BLUE_API b_status b_path_make_canonical(const b_path *in, b_path **out);
|
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 b_path *b_path_retain(b_path *path);
|
||||||
BLUE_API void b_path_release(b_path *path);
|
BLUE_API void b_path_release(b_path *path);
|
||||||
|
|||||||
36
io/sys/windows/directory.c
Normal file
36
io/sys/windows/directory.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include <blue/io/directory.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
234
io/sys/windows/path.c
Normal file
234
io/sys/windows/path.c
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <blue/core/stringstream.h>
|
||||||
|
#include <blue/io/path.h>
|
||||||
|
#include <blue/object/string.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user