Files
bluelib/io/sys/darwin/path.c

207 lines
3.7 KiB
C

#include <blue/core/stringstream.h>
#include <blue/io/path.h>
#include <blue/object/string.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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 = "/";
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()
{
char *buf = malloc(_PC_PATH_MAX);
if (!buf) {
return NULL;
}
if (!getcwd(buf, _PC_PATH_MAX)) {
free(buf);
return NULL;
}
struct b_path *path = b_path_create();
if (!path) {
free(buf);
return NULL;
}
b_string_append_cstr(path->pathstr, buf);
free(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_get_size(dest->pathstr, B_STRLEN_NORMAL) > 0
&& 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++) {
if (paths[i]) {
append_path(result, paths[i]);
}
}
return result;
}
struct b_path *b_path_make_absolute(const struct b_path *in)
{
return NULL;
}
struct b_path *b_path_make_relative(const struct b_path *in)
{
return NULL;
}
struct b_path *b_path_make_canonical(const struct b_path *in)
{
return NULL;
}
bool b_path_is_absolute(const struct b_path *path)
{
const char *s = b_string_ptr(path->pathstr);
return s[0] == '/';
}
bool b_path_exists(const struct b_path *path)
{
return false;
}
bool b_path_is_file(const struct b_path *path)
{
return false;
}
bool b_path_is_directory(const struct b_path *path)
{
return false;
}
const char *b_path_ptr(const struct b_path *path)
{
return b_string_ptr(path->pathstr);
}
size_t b_path_length(const struct b_path *path)
{
return b_string_get_size(path->pathstr, B_STRLEN_NORMAL);
}
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));
}