Compare commits
8 Commits
c29c687076
...
181a6bac09
| Author | SHA1 | Date | |
|---|---|---|---|
| 181a6bac09 | |||
| 24bcb18543 | |||
| e9a1bfbde2 | |||
| 5c837abc6c | |||
| ad27b0cf73 | |||
| dbd2135998 | |||
| 50706084eb | |||
| 38699a0eb3 |
@@ -546,6 +546,56 @@ static fx_status to_string(
|
|||||||
return FX_SUCCESS;
|
return FX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fx_status clone(const fx_value *src_v, fx_value *dest_v)
|
||||||
|
{
|
||||||
|
fx_hashtable *src_table = NULL, *dest_table = NULL;
|
||||||
|
fx_value_get_object(src_v, &src_table);
|
||||||
|
|
||||||
|
dest_table = fx_hashtable_create();
|
||||||
|
if (!dest_table) {
|
||||||
|
return FX_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_hashtable_p *src_p
|
||||||
|
= fx_object_get_private(src_table, FX_TYPE_HASHTABLE);
|
||||||
|
struct fx_hashtable_p *dest_p
|
||||||
|
= fx_object_get_private(dest_table, FX_TYPE_HASHTABLE);
|
||||||
|
dest_p->t_count = src_p->t_count;
|
||||||
|
dest_p->t_max_index = src_p->t_max_index;
|
||||||
|
size_t capacity = primes[dest_p->t_max_index];
|
||||||
|
dest_p->t_items = calloc(capacity, sizeof *dest_p->t_items);
|
||||||
|
if (!dest_p->t_items) {
|
||||||
|
fx_hashtable_unref(dest_table);
|
||||||
|
return FX_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < capacity; i++) {
|
||||||
|
if (!src_p->t_items[i].i_item) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_hashtable *new_item
|
||||||
|
= fx_object_create(FX_TYPE_HASHTABLE_ITEM);
|
||||||
|
if (!new_item) {
|
||||||
|
fx_hashtable_unref(dest_table);
|
||||||
|
return FX_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_hashtable_item_p *src_item_p = fx_object_get_private(
|
||||||
|
src_p->t_items[i].i_item,
|
||||||
|
FX_TYPE_HASHTABLE_ITEM);
|
||||||
|
struct fx_hashtable_item_p *new_item_p = fx_object_get_private(
|
||||||
|
new_item,
|
||||||
|
FX_TYPE_HASHTABLE_ITEM);
|
||||||
|
new_item_p->i_key = fx_value_copy_return(src_item_p->i_key);
|
||||||
|
new_item_p->i_value = fx_value_copy_return(src_item_p->i_value);
|
||||||
|
dest_p->t_items[i].i_item = new_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest_v = FX_VALUE_OBJECT(dest_table);
|
||||||
|
return FX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static fx_status get_key(
|
static fx_status get_key(
|
||||||
const fx_value *item_value,
|
const fx_value *item_value,
|
||||||
const fx_property *prop,
|
const fx_property *prop,
|
||||||
@@ -655,6 +705,7 @@ static const fx_value *iterator_get_value(const fx_iterator *obj)
|
|||||||
FX_TYPE_CLASS_BEGIN(fx_hashtable)
|
FX_TYPE_CLASS_BEGIN(fx_hashtable)
|
||||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||||
FX_INTERFACE_ENTRY(to_string) = to_string;
|
FX_INTERFACE_ENTRY(to_string) = to_string;
|
||||||
|
FX_INTERFACE_ENTRY(clone) = clone;
|
||||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||||
|
|
||||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterable, FX_TYPE_ITERABLE)
|
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterable, FX_TYPE_ITERABLE)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef FX_DIAGNOSTICS_PROCESS_H_
|
#ifndef FX_DIAGNOSTICS_PROCESS_H_
|
||||||
#define FX_DIAGNOSTICS_PROCESS_H_
|
#define FX_DIAGNOSTICS_PROCESS_H_
|
||||||
|
|
||||||
|
#include <fx/collections/array.h>
|
||||||
#include <fx/collections/hashtable.h>
|
#include <fx/collections/hashtable.h>
|
||||||
#include <fx/macros.h>
|
#include <fx/macros.h>
|
||||||
#include <fx/stream.h>
|
#include <fx/stream.h>
|
||||||
@@ -17,8 +18,7 @@ FX_TYPE_CLASS_DECLARATION_END(fx_process)
|
|||||||
typedef struct fx_process_start_info {
|
typedef struct fx_process_start_info {
|
||||||
bool proc_redirect_stdin, proc_redirect_stdout, proc_redirect_stderr;
|
bool proc_redirect_stdin, proc_redirect_stdout, proc_redirect_stderr;
|
||||||
const char *proc_file_name;
|
const char *proc_file_name;
|
||||||
const char **proc_args;
|
const fx_array *proc_args;
|
||||||
size_t proc_args_count;
|
|
||||||
const fx_hashtable *proc_environment;
|
const fx_hashtable *proc_environment;
|
||||||
} fx_process_start_info;
|
} fx_process_start_info;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include <fx/collections/array.h>
|
#include <fx/collections/array.h>
|
||||||
#include <fx/diagnostics/process.h>
|
#include <fx/diagnostics/process.h>
|
||||||
|
#include <fx/global.h>
|
||||||
|
#include <fx/io/path.h>
|
||||||
#include <fx/io/pipe.h>
|
#include <fx/io/pipe.h>
|
||||||
#include <fx/io/stream.h>
|
#include <fx/io/stream.h>
|
||||||
#include <fx/iterator.h>
|
#include <fx/iterator.h>
|
||||||
#include <fx/macros.h>
|
#include <fx/macros.h>
|
||||||
#include <fx/string.h>
|
#include <fx/string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static fx_process *self = NULL;
|
||||||
|
|
||||||
|
extern const char **environ;
|
||||||
|
|
||||||
FX_API fx_type_id fx_process_iterator_get_type();
|
FX_API fx_type_id fx_process_iterator_get_type();
|
||||||
|
|
||||||
FX_DECLARE_TYPE(fx_process_iterator);
|
FX_DECLARE_TYPE(fx_process_iterator);
|
||||||
@@ -21,6 +30,7 @@ struct fx_process_p {
|
|||||||
bool proc_redirect_stdin, proc_redirect_stdout, proc_redirect_stderr;
|
bool proc_redirect_stdin, proc_redirect_stdout, proc_redirect_stderr;
|
||||||
fx_stream *proc_stdin, *proc_stdout, *proc_stderr;
|
fx_stream *proc_stdin, *proc_stdout, *proc_stderr;
|
||||||
pid_t proc_id;
|
pid_t proc_id;
|
||||||
|
fx_hashtable *proc_environment;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fx_process_iterator_p {
|
struct fx_process_iterator_p {
|
||||||
@@ -28,12 +38,109 @@ struct fx_process_iterator_p {
|
|||||||
|
|
||||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static bool exec_name_is_path(const char *s)
|
||||||
|
{
|
||||||
|
fx_wchar c;
|
||||||
|
while (*s) {
|
||||||
|
c = fx_wchar_utf8_codepoint_decode(s);
|
||||||
|
if (c == FX_WCHAR_INVALID) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '/') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += fx_wchar_utf8_codepoint_stride(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fx_string *get_path(void)
|
||||||
|
{
|
||||||
|
const char *path_env = NULL;
|
||||||
|
fx_process *self = fx_process_get_self();
|
||||||
|
if (!self) {
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fx_hashtable *env = fx_process_get_environment(self);
|
||||||
|
if (!env) {
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fx_value *path_v = fx_hashtable_get(env, &FX_CSTR("PATH"));
|
||||||
|
if (!path_v) {
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_string *result = NULL;
|
||||||
|
fx_value_get_object(path_v, &result);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fallback:
|
||||||
|
path_env = getenv("PATH");
|
||||||
|
if (!path_env) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fx_string_create_from_cstr(path_env);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fx_status find_executable(fx_string *exec_path)
|
||||||
|
{
|
||||||
|
const char *exec_path_cstr = fx_string_get_cstr(exec_path);
|
||||||
|
const fx_string *path_env = get_path();
|
||||||
|
if (!path_env) {
|
||||||
|
return FX_ERR_NO_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *delim[] = {":"};
|
||||||
|
size_t nr_delim = sizeof delim / sizeof delim[0];
|
||||||
|
fx_path *path = NULL;
|
||||||
|
fx_iterator *it = fx_string_tokenise(
|
||||||
|
path_env,
|
||||||
|
delim,
|
||||||
|
nr_delim,
|
||||||
|
FX_STRING_TOK_F_NORMAL);
|
||||||
|
fx_status status = FX_ERR_NO_ENTRY;
|
||||||
|
|
||||||
|
fx_foreach(tok, it)
|
||||||
|
{
|
||||||
|
path = fx_path_join_list(2, tok, &FX_VALUE_OBJECT(exec_path));
|
||||||
|
if (fx_path_is_file(path)) {
|
||||||
|
fx_string_clear(exec_path);
|
||||||
|
fx_string_append_cstr(
|
||||||
|
exec_path,
|
||||||
|
fx_path_get_cstr(path));
|
||||||
|
status = FX_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_iterator_unref(it);
|
||||||
|
fx_path_unref(path);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static fx_status process_start(struct fx_process_p *proc)
|
static fx_status process_start(struct fx_process_p *proc)
|
||||||
{
|
{
|
||||||
fx_iostream *in_r = NULL, *in_w = NULL;
|
fx_iostream *in_r = NULL, *in_w = NULL;
|
||||||
fx_iostream *out_r = NULL, *out_w = NULL;
|
fx_iostream *out_r = NULL, *out_w = NULL;
|
||||||
fx_iostream *err_r = NULL, *err_w = NULL;
|
fx_iostream *err_r = NULL, *err_w = NULL;
|
||||||
fx_status status = FX_SUCCESS;
|
fx_status status = FX_SUCCESS;
|
||||||
|
bool name_is_path
|
||||||
|
= exec_name_is_path(fx_string_get_cstr(proc->proc_exec_path));
|
||||||
|
|
||||||
|
if (!name_is_path) {
|
||||||
|
status = find_executable(proc->proc_exec_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
if (proc->proc_redirect_stdin) {
|
if (proc->proc_redirect_stdin) {
|
||||||
status = fx_pipe_create(&in_r, &in_w);
|
status = fx_pipe_create(&in_r, &in_w);
|
||||||
@@ -76,7 +183,6 @@ static fx_status process_start(struct fx_process_p *proc)
|
|||||||
if (proc->proc_redirect_stdin) {
|
if (proc->proc_redirect_stdin) {
|
||||||
fx_iostream_unref(in_w);
|
fx_iostream_unref(in_w);
|
||||||
fd = fx_iostream_steal_os_handle(in_r);
|
fd = fx_iostream_steal_os_handle(in_r);
|
||||||
fprintf(stderr, "dup2(%d, %d)\n", fd, 0);
|
|
||||||
int err = dup2(fd, 0);
|
int err = dup2(fd, 0);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@@ -96,12 +202,23 @@ static fx_status process_start(struct fx_process_p *proc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char **argv = NULL;
|
const char **argv = NULL;
|
||||||
|
const char **envp = NULL;
|
||||||
|
const char *default_argv[] = {
|
||||||
|
fx_string_get_cstr(proc->proc_exec_path),
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
size_t argc = 0;
|
size_t argc = 0;
|
||||||
|
size_t envc = 0;
|
||||||
|
|
||||||
if (proc->proc_args) {
|
if (proc->proc_args) {
|
||||||
argc = fx_array_get_size(proc->proc_args);
|
argc = fx_array_get_size(proc->proc_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proc->proc_environment) {
|
||||||
|
envc = fx_hashtable_get_count(proc->proc_environment);
|
||||||
|
}
|
||||||
|
|
||||||
if (argc) {
|
if (argc) {
|
||||||
argv = calloc(argc + 1, sizeof(char *));
|
argv = calloc(argc + 1, sizeof(char *));
|
||||||
|
|
||||||
@@ -110,9 +227,38 @@ static fx_status process_start(struct fx_process_p *proc)
|
|||||||
= fx_array_get_ref(proc->proc_args, i);
|
= fx_array_get_ref(proc->proc_args, i);
|
||||||
fx_value_get_cstr(arg_value, &argv[i]);
|
fx_value_get_cstr(arg_value, &argv[i]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
argv = default_argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
execv(fx_string_get_cstr(proc->proc_exec_path), (char *const *)argv);
|
if (envc) {
|
||||||
|
envp = calloc(envc + 1, sizeof(char *));
|
||||||
|
size_t i = 0;
|
||||||
|
fx_stringstream *tmp = fx_stringstream_create();
|
||||||
|
const fx_iterator *it
|
||||||
|
= fx_iterator_begin(proc->proc_environment);
|
||||||
|
fx_foreach(v, it)
|
||||||
|
{
|
||||||
|
fx_hashtable_item *item = NULL;
|
||||||
|
fx_value_get_object(v, &item);
|
||||||
|
const fx_value *name_v
|
||||||
|
= fx_hashtable_item_get_key(item);
|
||||||
|
const fx_value *value_v
|
||||||
|
= fx_hashtable_item_get_value(item);
|
||||||
|
|
||||||
|
fx_value_to_string(name_v, tmp, NULL);
|
||||||
|
fx_stream_write_char(tmp, '=');
|
||||||
|
fx_value_to_string(value_v, tmp, NULL);
|
||||||
|
envp[i++] = fx_stringstream_steal(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_iterator_unref(it);
|
||||||
|
fx_string_unref(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
execve(fx_string_get_cstr(proc->proc_exec_path),
|
||||||
|
(char *const *)argv,
|
||||||
|
(char *const *)envp);
|
||||||
exit(127);
|
exit(127);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -159,6 +305,12 @@ static fx_status process_kill(struct fx_process_p *proc)
|
|||||||
return FX_SUCCESS;
|
return FX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const fx_hashtable *process_get_environment(
|
||||||
|
const struct fx_process_p *proc)
|
||||||
|
{
|
||||||
|
return proc->proc_environment;
|
||||||
|
}
|
||||||
|
|
||||||
static fx_stream *process_get_stdin(struct fx_process_p *proc)
|
static fx_stream *process_get_stdin(struct fx_process_p *proc)
|
||||||
{
|
{
|
||||||
return proc->proc_stdin;
|
return proc->proc_stdin;
|
||||||
@@ -210,25 +362,10 @@ fx_process *fx_process_create(const fx_process_start_info *info)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->proc_args_count > 0) {
|
proc->proc_args = fx_array_ref((fx_array *)info->proc_args);
|
||||||
proc->proc_args = fx_array_create();
|
|
||||||
if (!proc->proc_args) {
|
|
||||||
fx_process_unref(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < info->proc_args_count; i++) {
|
|
||||||
fx_string *arg = fx_string_create_from_cstr(info->proc_args[i]);
|
|
||||||
if (!arg) {
|
|
||||||
fx_process_unref(out);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fx_array_push_back(proc->proc_args, FX_VALUE_OBJECT(arg));
|
|
||||||
fx_string_unref(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
proc->proc_environment
|
||||||
|
= fx_hashtable_ref((fx_hashtable *)info->proc_environment);
|
||||||
proc->proc_redirect_stdin = info->proc_redirect_stdin;
|
proc->proc_redirect_stdin = info->proc_redirect_stdin;
|
||||||
proc->proc_redirect_stdout = info->proc_redirect_stdout;
|
proc->proc_redirect_stdout = info->proc_redirect_stdout;
|
||||||
proc->proc_redirect_stderr = info->proc_redirect_stderr;
|
proc->proc_redirect_stderr = info->proc_redirect_stderr;
|
||||||
@@ -236,6 +373,56 @@ fx_process *fx_process_create(const fx_process_start_info *info)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fx_process *fx_process_get_self(void)
|
||||||
|
{
|
||||||
|
if (self) {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = fx_object_create(FX_DIAGNOSTICS_TYPE_PROCESS);
|
||||||
|
if (!self) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_process_p *proc
|
||||||
|
= fx_object_get_private(self, FX_DIAGNOSTICS_TYPE_PROCESS);
|
||||||
|
|
||||||
|
proc->proc_id = getpid();
|
||||||
|
fx_hashtable *env = fx_hashtable_create();
|
||||||
|
|
||||||
|
for (size_t i = 0; environ[i]; i++) {
|
||||||
|
char *envstr = fx_strdup(environ[i]);
|
||||||
|
|
||||||
|
const char *name = envstr;
|
||||||
|
char *sep = strchr(name, '=');
|
||||||
|
const char *value = NULL;
|
||||||
|
if (sep) {
|
||||||
|
*sep = '\0';
|
||||||
|
value = sep + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_string *name_str = fx_string_create_from_cstr(name);
|
||||||
|
fx_string *value_str = fx_string_create();
|
||||||
|
if (value) {
|
||||||
|
fx_string_append_cstr(value_str, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_hashtable_put(
|
||||||
|
env,
|
||||||
|
&FX_VALUE_OBJECT(name_str),
|
||||||
|
&FX_VALUE_OBJECT(value_str));
|
||||||
|
|
||||||
|
fx_string_unref(name_str);
|
||||||
|
fx_string_unref(value_str);
|
||||||
|
free(envstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->proc_environment = env;
|
||||||
|
|
||||||
|
fx_register_global(self);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
fx_status fx_process_start(fx_process *proc)
|
fx_status fx_process_start(fx_process *proc)
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC_0(
|
FX_CLASS_DISPATCH_STATIC_0(
|
||||||
@@ -261,6 +448,14 @@ fx_status fx_process_kill(fx_process *proc)
|
|||||||
proc);
|
proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fx_hashtable *fx_process_get_environment(const fx_process *proc)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(
|
||||||
|
FX_DIAGNOSTICS_TYPE_PROCESS,
|
||||||
|
process_get_environment,
|
||||||
|
proc);
|
||||||
|
}
|
||||||
|
|
||||||
fx_stream *fx_process_get_stdin(fx_process *proc)
|
fx_stream *fx_process_get_stdin(fx_process *proc)
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC_0(
|
FX_CLASS_DISPATCH_STATIC_0(
|
||||||
@@ -317,6 +512,13 @@ static void process_init(fx_object *obj, void *priv)
|
|||||||
|
|
||||||
static void process_fini(fx_object *obj, void *priv)
|
static void process_fini(fx_object *obj, void *priv)
|
||||||
{
|
{
|
||||||
|
struct fx_process_p *proc = priv;
|
||||||
|
fx_array_unref(proc->proc_args);
|
||||||
|
fx_iostream_unref(proc->proc_stdin);
|
||||||
|
fx_iostream_unref(proc->proc_stdout);
|
||||||
|
fx_iostream_unref(proc->proc_stderr);
|
||||||
|
fx_string_unref(proc->proc_exec_path);
|
||||||
|
fx_hashtable_unref(proc->proc_environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** ITERATOR DEFINITION ******************************************************/
|
/*** ITERATOR DEFINITION ******************************************************/
|
||||||
|
|||||||
@@ -9,17 +9,19 @@ int main(int argc, const char **argv)
|
|||||||
const char *exec = argv[1];
|
const char *exec = argv[1];
|
||||||
const char *msg = argv[2];
|
const char *msg = argv[2];
|
||||||
|
|
||||||
const char *args[] = {
|
const fx_value arg_values[] = {
|
||||||
"hello",
|
FX_CSTR("hello"),
|
||||||
"world",
|
FX_CSTR("world"),
|
||||||
};
|
};
|
||||||
|
fx_array *args = fx_array_create_with_values(
|
||||||
|
arg_values,
|
||||||
|
sizeof arg_values / sizeof arg_values[0]);
|
||||||
|
|
||||||
fx_process *self = fx_process_get_self();
|
fx_process *self = fx_process_get_self();
|
||||||
const fx_hashtable *env = fx_process_get_environment(self);
|
const fx_hashtable *env = fx_process_get_environment(self);
|
||||||
|
|
||||||
fx_process_start_info info = {
|
fx_process_start_info info = {
|
||||||
.proc_args = args,
|
.proc_args = args,
|
||||||
.proc_args_count = sizeof args / sizeof args[0],
|
|
||||||
.proc_redirect_stdout = true,
|
.proc_redirect_stdout = true,
|
||||||
.proc_redirect_stdin = true,
|
.proc_redirect_stdin = true,
|
||||||
.proc_file_name = exec,
|
.proc_file_name = exec,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ FX_API fx_type_id fx_directory_iterator_get_type(void);
|
|||||||
|
|
||||||
FX_API fx_result fx_directory_open(
|
FX_API fx_result fx_directory_open(
|
||||||
fx_directory *root,
|
fx_directory *root,
|
||||||
const fx_path *path,
|
fx_value path,
|
||||||
fx_directory_open_flags flags,
|
fx_directory_open_flags flags,
|
||||||
fx_directory **out);
|
fx_directory **out);
|
||||||
FX_API fx_result fx_directory_open_temp(fx_directory **out);
|
FX_API fx_result fx_directory_open_temp(fx_directory **out);
|
||||||
@@ -60,22 +60,17 @@ FX_API const char *fx_directory_get_path_cstr(const fx_directory *dir);
|
|||||||
FX_API const char *fx_directory_get_rel_path_cstr(const fx_directory *dir);
|
FX_API const char *fx_directory_get_rel_path_cstr(const fx_directory *dir);
|
||||||
FX_API fx_result fx_directory_delete(fx_directory *dir);
|
FX_API fx_result fx_directory_delete(fx_directory *dir);
|
||||||
|
|
||||||
FX_API bool fx_directory_path_exists(
|
FX_API bool fx_directory_path_exists(const fx_directory *root, fx_value path);
|
||||||
const fx_directory *root,
|
FX_API bool fx_directory_path_is_file(const fx_directory *root, fx_value path);
|
||||||
const fx_path *path);
|
|
||||||
FX_API bool fx_directory_path_is_file(
|
|
||||||
const fx_directory *root,
|
|
||||||
const fx_path *path);
|
|
||||||
FX_API bool fx_directory_path_is_directory(
|
FX_API bool fx_directory_path_is_directory(
|
||||||
const fx_directory *root,
|
const fx_directory *root,
|
||||||
const fx_path *path);
|
fx_value path);
|
||||||
FX_API fx_result fx_directory_path_stat(
|
FX_API fx_result fx_directory_path_stat(
|
||||||
const fx_directory *root,
|
const fx_directory *root,
|
||||||
const fx_path *path,
|
fx_value path,
|
||||||
struct fx_file_info *out);
|
struct fx_file_info *out);
|
||||||
FX_API fx_result fx_directory_path_unlink(
|
FX_API fx_result
|
||||||
const fx_directory *root,
|
fx_directory_path_unlink(const fx_directory *root, fx_value path);
|
||||||
const fx_path *path);
|
|
||||||
|
|
||||||
FX_API fx_iterator *fx_directory_begin(
|
FX_API fx_iterator *fx_directory_begin(
|
||||||
fx_directory *dir,
|
fx_directory *dir,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <fx/macros.h>
|
#include <fx/macros.h>
|
||||||
#include <fx/misc.h>
|
#include <fx/misc.h>
|
||||||
#include <fx/stream.h>
|
#include <fx/stream.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
|
||||||
FX_DECLS_BEGIN;
|
FX_DECLS_BEGIN;
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ FX_API fx_type_id fx_file_get_type(void);
|
|||||||
|
|
||||||
FX_API fx_result fx_file_open(
|
FX_API fx_result fx_file_open(
|
||||||
FX_TYPE_FWDREF(fx_directory) * root,
|
FX_TYPE_FWDREF(fx_directory) * root,
|
||||||
const FX_TYPE_FWDREF(fx_path) * path,
|
fx_value path,
|
||||||
fx_file_mode mode,
|
fx_file_mode mode,
|
||||||
fx_file **out);
|
fx_file **out);
|
||||||
FX_API fx_result fx_file_open_temp(fx_file_mode mode, fx_file **out);
|
FX_API fx_result fx_file_open_temp(fx_file_mode mode, fx_file **out);
|
||||||
|
|||||||
+71
-79
@@ -1,3 +1,5 @@
|
|||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "posix.h"
|
#include "posix.h"
|
||||||
|
|
||||||
@@ -65,9 +67,8 @@ static fx_result directory_delete(
|
|||||||
{
|
{
|
||||||
enum fx_status status = FX_SUCCESS;
|
enum fx_status status = FX_SUCCESS;
|
||||||
|
|
||||||
fx_iterator *it = fx_directory_begin(
|
fx_iterator *it
|
||||||
dir,
|
= fx_directory_begin(dir, FX_DIRECTORY_ITERATE_PARENT_LAST);
|
||||||
FX_DIRECTORY_ITERATE_PARENT_LAST);
|
|
||||||
while (FX_OK(fx_iterator_get_status(it))) {
|
while (FX_OK(fx_iterator_get_status(it))) {
|
||||||
fx_iterator_erase(it);
|
fx_iterator_erase(it);
|
||||||
}
|
}
|
||||||
@@ -87,14 +88,12 @@ static fx_result directory_delete(
|
|||||||
|
|
||||||
static bool directory_path_exists(
|
static bool directory_path_exists(
|
||||||
const struct fx_directory_p *root,
|
const struct fx_directory_p *root,
|
||||||
const fx_path *path)
|
fx_value path)
|
||||||
{
|
{
|
||||||
const fx_path *parts[] = {
|
fx_path *abs_path = fx_path_join_list(
|
||||||
root ? root->d_path_abs : NULL,
|
2,
|
||||||
path,
|
&FX_VALUE_OBJECT(root ? root->d_path_abs : NULL),
|
||||||
};
|
&path);
|
||||||
|
|
||||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
|
||||||
if (!abs_path) {
|
if (!abs_path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -107,14 +106,14 @@ static bool directory_path_exists(
|
|||||||
|
|
||||||
static bool directory_path_is_file(
|
static bool directory_path_is_file(
|
||||||
const struct fx_directory_p *root,
|
const struct fx_directory_p *root,
|
||||||
const fx_path *path)
|
fx_value path)
|
||||||
{
|
{
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {};
|
||||||
root ? root->d_path_abs : NULL,
|
|
||||||
path,
|
|
||||||
};
|
|
||||||
|
|
||||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
fx_path *abs_path = fx_path_join_list(
|
||||||
|
2,
|
||||||
|
&FX_VALUE_OBJECT(root ? root->d_path_abs : NULL),
|
||||||
|
&path);
|
||||||
if (!abs_path) {
|
if (!abs_path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -127,14 +126,14 @@ static bool directory_path_is_file(
|
|||||||
|
|
||||||
static bool directory_path_is_directory(
|
static bool directory_path_is_directory(
|
||||||
const struct fx_directory_p *root,
|
const struct fx_directory_p *root,
|
||||||
const fx_path *path)
|
fx_value path)
|
||||||
{
|
{
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {};
|
||||||
root ? root->d_path_abs : NULL,
|
|
||||||
path,
|
|
||||||
};
|
|
||||||
|
|
||||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
fx_path *abs_path = fx_path_join_list(
|
||||||
|
2,
|
||||||
|
&FX_VALUE_OBJECT(root ? root->d_path_abs : NULL),
|
||||||
|
&path);
|
||||||
if (!abs_path) {
|
if (!abs_path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -147,15 +146,15 @@ static bool directory_path_is_directory(
|
|||||||
|
|
||||||
static fx_result directory_path_stat(
|
static fx_result directory_path_stat(
|
||||||
const struct fx_directory_p *root,
|
const struct fx_directory_p *root,
|
||||||
const fx_path *path,
|
fx_value path,
|
||||||
struct fx_file_info *out)
|
struct fx_file_info *out)
|
||||||
{
|
{
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {};
|
||||||
root ? root->d_path_abs : NULL,
|
|
||||||
path,
|
|
||||||
};
|
|
||||||
|
|
||||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
fx_path *abs_path = fx_path_join_list(
|
||||||
|
2,
|
||||||
|
&FX_VALUE_OBJECT(root ? root->d_path_abs : NULL),
|
||||||
|
&path);
|
||||||
if (!abs_path) {
|
if (!abs_path) {
|
||||||
return FX_RESULT_ERR(NO_MEMORY);
|
return FX_RESULT_ERR(NO_MEMORY);
|
||||||
}
|
}
|
||||||
@@ -168,14 +167,14 @@ static fx_result directory_path_stat(
|
|||||||
|
|
||||||
static fx_result directory_path_unlink(
|
static fx_result directory_path_unlink(
|
||||||
const struct fx_directory_p *root,
|
const struct fx_directory_p *root,
|
||||||
const fx_path *path)
|
fx_value path)
|
||||||
{
|
{
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {};
|
||||||
root ? root->d_path_abs : NULL,
|
|
||||||
path,
|
|
||||||
};
|
|
||||||
|
|
||||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
fx_path *abs_path = fx_path_join_list(
|
||||||
|
2,
|
||||||
|
&FX_VALUE_OBJECT(root ? root->d_path_abs : NULL),
|
||||||
|
&path);
|
||||||
if (!abs_path) {
|
if (!abs_path) {
|
||||||
return FX_RESULT_ERR(NO_MEMORY);
|
return FX_RESULT_ERR(NO_MEMORY);
|
||||||
}
|
}
|
||||||
@@ -255,7 +254,7 @@ static fx_result create_directory_hierarchy(
|
|||||||
|
|
||||||
static fx_result directory_open(
|
static fx_result directory_open(
|
||||||
struct fx_directory_p *root,
|
struct fx_directory_p *root,
|
||||||
const fx_path *path,
|
fx_value path,
|
||||||
fx_directory_open_flags flags,
|
fx_directory_open_flags flags,
|
||||||
fx_directory **out)
|
fx_directory **out)
|
||||||
{
|
{
|
||||||
@@ -263,7 +262,10 @@ static fx_result directory_open(
|
|||||||
|
|
||||||
int root_fd = root ? root->d_fd : AT_FDCWD;
|
int root_fd = root ? root->d_fd : AT_FDCWD;
|
||||||
|
|
||||||
const char *path_cstr = fx_path_get_cstr(path);
|
fx_stringstream *path_str = fx_stringstream_create();
|
||||||
|
fx_value_to_string(&path, path_str, NULL);
|
||||||
|
const char *path_cstr = fx_stringstream_get_cstr(path_str);
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
while (*path_cstr == '/') {
|
while (*path_cstr == '/') {
|
||||||
path_cstr++;
|
path_cstr++;
|
||||||
@@ -293,21 +295,22 @@ static fx_result directory_open(
|
|||||||
|
|
||||||
fx_directory *dir = fx_object_create(FX_TYPE_DIRECTORY);
|
fx_directory *dir = fx_object_create(FX_TYPE_DIRECTORY);
|
||||||
fx_path *cwd = NULL;
|
fx_path *cwd = NULL;
|
||||||
struct fx_directory_p *p = fx_object_get_private(
|
struct fx_directory_p *p
|
||||||
dir,
|
= fx_object_get_private(dir, FX_TYPE_DIRECTORY);
|
||||||
FX_TYPE_DIRECTORY);
|
|
||||||
|
|
||||||
if (!root) {
|
if (!root) {
|
||||||
cwd = fx_path_create_cwd();
|
cwd = fx_path_get_system(FX_PATH_CWD);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {
|
||||||
root ? root->d_path_abs : cwd,
|
&FX_VALUE_OBJECT(root ? root->d_path_abs : cwd),
|
||||||
path,
|
&FX_CSTR(path_cstr),
|
||||||
};
|
};
|
||||||
|
|
||||||
fx_path *new_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
fx_path *new_path
|
||||||
|
= fx_path_join_array(parts, sizeof parts / sizeof parts[0]);
|
||||||
if (!new_path) {
|
if (!new_path) {
|
||||||
|
fx_stringstream_unref(path_str);
|
||||||
return FX_RESULT_ERR(NO_MEMORY);
|
return FX_RESULT_ERR(NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +319,7 @@ static fx_result directory_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
p->d_path_abs = new_path;
|
p->d_path_abs = new_path;
|
||||||
p->d_path_rel = fx_path_duplicate(path);
|
p->d_path_rel = fx_path_create_from_cstr(path_cstr);
|
||||||
p->d_fd = fd;
|
p->d_fd = fd;
|
||||||
|
|
||||||
if (flags & FX_DIRECTORY_OPEN_DELETE_ON_CLOSE) {
|
if (flags & FX_DIRECTORY_OPEN_DELETE_ON_CLOSE) {
|
||||||
@@ -324,6 +327,7 @@ static fx_result directory_open(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*out = dir;
|
*out = dir;
|
||||||
|
fx_stringstream_unref(path_str);
|
||||||
|
|
||||||
return FX_RESULT_SUCCESS;
|
return FX_RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -332,7 +336,7 @@ static fx_result directory_open(
|
|||||||
|
|
||||||
fx_result fx_directory_open(
|
fx_result fx_directory_open(
|
||||||
fx_directory *root,
|
fx_directory *root,
|
||||||
const fx_path *path,
|
fx_value path,
|
||||||
fx_directory_open_flags flags,
|
fx_directory_open_flags flags,
|
||||||
fx_directory **out)
|
fx_directory **out)
|
||||||
{
|
{
|
||||||
@@ -353,20 +357,17 @@ fx_result fx_directory_open_temp(fx_directory **out)
|
|||||||
while (1) {
|
while (1) {
|
||||||
z__fx_io_generate_tmp_filename(name, sizeof name);
|
z__fx_io_generate_tmp_filename(name, sizeof name);
|
||||||
snprintf(path, sizeof path, "/tmp/%s", name);
|
snprintf(path, sizeof path, "/tmp/%s", name);
|
||||||
fx_path *rpath = fx_path_create_from_cstr(path);
|
|
||||||
|
|
||||||
fx_directory *dir = NULL;
|
fx_directory *dir = NULL;
|
||||||
fx_result status = fx_directory_open(
|
fx_result status = fx_directory_open(
|
||||||
FX_DIRECTORY_ROOT,
|
FX_DIRECTORY_ROOT,
|
||||||
rpath,
|
FX_CSTR(path),
|
||||||
FX_DIRECTORY_OPEN_CREATE,
|
FX_DIRECTORY_OPEN_CREATE,
|
||||||
&dir);
|
&dir);
|
||||||
struct fx_directory_p *p = fx_object_get_private(
|
struct fx_directory_p *p
|
||||||
dir,
|
= fx_object_get_private(dir, FX_TYPE_DIRECTORY);
|
||||||
FX_TYPE_DIRECTORY);
|
|
||||||
|
|
||||||
if (fx_error_get_status_code(status) == FX_ERR_NAME_EXISTS) {
|
if (fx_error_get_status_code(status) == FX_ERR_NAME_EXISTS) {
|
||||||
fx_path_unref(rpath);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,8 +375,8 @@ fx_result fx_directory_open_temp(fx_directory **out)
|
|||||||
p->d_flags |= DIRECTORY_DELETE_ON_CLOSE;
|
p->d_flags |= DIRECTORY_DELETE_ON_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_path_unlink(rpath);
|
*out = dir;
|
||||||
fx_path_unref(rpath);
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,16 +411,15 @@ const char *fx_directory_get_rel_path_cstr(const fx_directory *dir)
|
|||||||
|
|
||||||
fx_result fx_directory_delete(fx_directory *dir)
|
fx_result fx_directory_delete(fx_directory *dir)
|
||||||
{
|
{
|
||||||
struct fx_directory_p *p = fx_object_get_private(
|
struct fx_directory_p *p
|
||||||
dir,
|
= fx_object_get_private(dir, FX_TYPE_DIRECTORY);
|
||||||
FX_TYPE_DIRECTORY);
|
|
||||||
p->d_flags |= DIRECTORY_DELETE_ON_CLOSE;
|
p->d_flags |= DIRECTORY_DELETE_ON_CLOSE;
|
||||||
/* TODO allow object release functions to return a fx_result value */
|
/* TODO allow object release functions to return a fx_result value */
|
||||||
fx_directory_unref(dir);
|
fx_directory_unref(dir);
|
||||||
return FX_RESULT_SUCCESS;
|
return FX_RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fx_directory_path_exists(const fx_directory *root, const fx_path *path)
|
bool fx_directory_path_exists(const fx_directory *root, fx_value path)
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC(
|
FX_CLASS_DISPATCH_STATIC(
|
||||||
FX_TYPE_DIRECTORY,
|
FX_TYPE_DIRECTORY,
|
||||||
@@ -428,7 +428,7 @@ bool fx_directory_path_exists(const fx_directory *root, const fx_path *path)
|
|||||||
path);
|
path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fx_directory_path_is_file(const fx_directory *root, const fx_path *path)
|
bool fx_directory_path_is_file(const fx_directory *root, fx_value path)
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC(
|
FX_CLASS_DISPATCH_STATIC(
|
||||||
FX_TYPE_DIRECTORY,
|
FX_TYPE_DIRECTORY,
|
||||||
@@ -437,9 +437,7 @@ bool fx_directory_path_is_file(const fx_directory *root, const fx_path *path)
|
|||||||
path);
|
path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fx_directory_path_is_directory(
|
bool fx_directory_path_is_directory(const fx_directory *root, fx_value path)
|
||||||
const fx_directory *root,
|
|
||||||
const fx_path *path)
|
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC(
|
FX_CLASS_DISPATCH_STATIC(
|
||||||
FX_TYPE_DIRECTORY,
|
FX_TYPE_DIRECTORY,
|
||||||
@@ -450,7 +448,7 @@ bool fx_directory_path_is_directory(
|
|||||||
|
|
||||||
fx_result fx_directory_path_stat(
|
fx_result fx_directory_path_stat(
|
||||||
const fx_directory *root,
|
const fx_directory *root,
|
||||||
const fx_path *path,
|
fx_value path,
|
||||||
struct fx_file_info *out)
|
struct fx_file_info *out)
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC(
|
FX_CLASS_DISPATCH_STATIC(
|
||||||
@@ -461,9 +459,7 @@ fx_result fx_directory_path_stat(
|
|||||||
out);
|
out);
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_result fx_directory_path_unlink(
|
fx_result fx_directory_path_unlink(const fx_directory *root, fx_value path)
|
||||||
const fx_directory *root,
|
|
||||||
const fx_path *path)
|
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC(
|
FX_CLASS_DISPATCH_STATIC(
|
||||||
FX_TYPE_DIRECTORY,
|
FX_TYPE_DIRECTORY,
|
||||||
@@ -560,9 +556,8 @@ fx_iterator *fx_directory_begin(
|
|||||||
enum fx_directory_iterator_flags flags)
|
enum fx_directory_iterator_flags flags)
|
||||||
{
|
{
|
||||||
fx_iterator *it_obj = fx_object_create(FX_TYPE_DIRECTORY_ITERATOR);
|
fx_iterator *it_obj = fx_object_create(FX_TYPE_DIRECTORY_ITERATOR);
|
||||||
struct fx_directory_iterator_p *it = fx_object_get_private(
|
struct fx_directory_iterator_p *it
|
||||||
it_obj,
|
= fx_object_get_private(it_obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||||
FX_TYPE_DIRECTORY_ITERATOR);
|
|
||||||
|
|
||||||
it->flags = flags;
|
it->flags = flags;
|
||||||
it->root = directory;
|
it->root = directory;
|
||||||
@@ -629,9 +624,8 @@ static const fx_iterator *iterator_begin(const fx_object *obj)
|
|||||||
|
|
||||||
static enum fx_status iterator_move_next(const fx_iterator *obj)
|
static enum fx_status iterator_move_next(const fx_iterator *obj)
|
||||||
{
|
{
|
||||||
struct fx_directory_iterator_p *it = fx_object_get_private(
|
struct fx_directory_iterator_p *it
|
||||||
obj,
|
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||||
FX_TYPE_DIRECTORY_ITERATOR);
|
|
||||||
if (!it || !it->fts) {
|
if (!it || !it->fts) {
|
||||||
return FX_ERR_NO_DATA;
|
return FX_ERR_NO_DATA;
|
||||||
}
|
}
|
||||||
@@ -679,12 +673,11 @@ static enum fx_status iterator_move_next(const fx_iterator *obj)
|
|||||||
|
|
||||||
static enum fx_status iterator_erase(fx_iterator *obj)
|
static enum fx_status iterator_erase(fx_iterator *obj)
|
||||||
{
|
{
|
||||||
struct fx_directory_iterator_p *it = fx_object_get_private(
|
struct fx_directory_iterator_p *it
|
||||||
obj,
|
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||||
FX_TYPE_DIRECTORY_ITERATOR);
|
|
||||||
fx_result result = fx_directory_path_unlink(
|
fx_result result = fx_directory_path_unlink(
|
||||||
it->root,
|
it->root,
|
||||||
it->entry.filepath);
|
FX_VALUE_OBJECT(it->entry.filepath));
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
enum fx_status status = fx_error_get_status_code(result);
|
enum fx_status status = fx_error_get_status_code(result);
|
||||||
fx_error_discard(result);
|
fx_error_discard(result);
|
||||||
@@ -696,9 +689,8 @@ static enum fx_status iterator_erase(fx_iterator *obj)
|
|||||||
|
|
||||||
static const fx_value *iterator_get_value(const fx_iterator *obj)
|
static const fx_value *iterator_get_value(const fx_iterator *obj)
|
||||||
{
|
{
|
||||||
struct fx_directory_iterator_p *it = fx_object_get_private(
|
struct fx_directory_iterator_p *it
|
||||||
obj,
|
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||||
FX_TYPE_DIRECTORY_ITERATOR);
|
|
||||||
|
|
||||||
return &it->entry_value;
|
return &it->entry_value;
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-20
@@ -1,3 +1,5 @@
|
|||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "posix.h"
|
#include "posix.h"
|
||||||
|
|
||||||
@@ -84,13 +86,13 @@ static fx_result file_open_shadow(
|
|||||||
= fx_path_create_from_cstr(fx_string_get_cstr(filename));
|
= fx_path_create_from_cstr(fx_string_get_cstr(filename));
|
||||||
fx_string_unref(filename);
|
fx_string_unref(filename);
|
||||||
|
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {
|
||||||
dir,
|
&FX_VALUE_OBJECT(dir),
|
||||||
shadow_filename,
|
&FX_VALUE_OBJECT(shadow_filename),
|
||||||
};
|
};
|
||||||
|
|
||||||
fx_path *shadow_filepath
|
fx_path *shadow_filepath
|
||||||
= fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
= fx_path_join_array(parts, sizeof parts / sizeof parts[0]);
|
||||||
fx_path_unref(dir);
|
fx_path_unref(dir);
|
||||||
fx_path_unref(shadow_filename);
|
fx_path_unref(shadow_filename);
|
||||||
|
|
||||||
@@ -101,7 +103,7 @@ static fx_result file_open_shadow(
|
|||||||
fx_file *shadow_file;
|
fx_file *shadow_file;
|
||||||
fx_result status = fx_file_open(
|
fx_result status = fx_file_open(
|
||||||
FX_DIRECTORY_ROOT,
|
FX_DIRECTORY_ROOT,
|
||||||
shadow_filepath,
|
FX_VALUE_OBJECT(shadow_filepath),
|
||||||
mode,
|
mode,
|
||||||
&shadow_file);
|
&shadow_file);
|
||||||
fx_path_unref(shadow_filepath);
|
fx_path_unref(shadow_filepath);
|
||||||
@@ -227,12 +229,14 @@ static enum fx_status file_swap_shadow(
|
|||||||
z__fx_io_generate_tmp_filename(tmp_name, sizeof tmp_name);
|
z__fx_io_generate_tmp_filename(tmp_name, sizeof tmp_name);
|
||||||
fx_path *tmp_name_p = fx_path_create_from_cstr(tmp_name);
|
fx_path *tmp_name_p = fx_path_create_from_cstr(tmp_name);
|
||||||
|
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {
|
||||||
dir_path,
|
&FX_VALUE_OBJECT(dir_path),
|
||||||
tmp_name_p,
|
&FX_VALUE_OBJECT(tmp_name_p),
|
||||||
};
|
};
|
||||||
|
|
||||||
tmp_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
tmp_path = fx_path_join_array(
|
||||||
|
parts,
|
||||||
|
sizeof parts / sizeof parts[0]);
|
||||||
|
|
||||||
fx_path_unref(tmp_name_p);
|
fx_path_unref(tmp_name_p);
|
||||||
|
|
||||||
@@ -248,11 +252,15 @@ static enum fx_status file_swap_shadow(
|
|||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = rename(fx_path_get_cstr(main_file->path), fx_path_get_cstr(tmp_path));
|
err = rename(
|
||||||
|
fx_path_get_cstr(main_file->path),
|
||||||
|
fx_path_get_cstr(tmp_path));
|
||||||
err = rename(
|
err = rename(
|
||||||
fx_path_get_cstr(shadow_file->path),
|
fx_path_get_cstr(shadow_file->path),
|
||||||
fx_path_get_cstr(main_file->path));
|
fx_path_get_cstr(main_file->path));
|
||||||
err = rename(fx_path_get_cstr(tmp_path), fx_path_get_cstr(shadow_file->path));
|
err = rename(
|
||||||
|
fx_path_get_cstr(tmp_path),
|
||||||
|
fx_path_get_cstr(shadow_file->path));
|
||||||
|
|
||||||
fx_path_unref(tmp_path);
|
fx_path_unref(tmp_path);
|
||||||
|
|
||||||
@@ -406,11 +414,10 @@ static enum fx_status stream_tell(const fx_stream *stream, size_t *pos)
|
|||||||
|
|
||||||
fx_result fx_file_open(
|
fx_result fx_file_open(
|
||||||
fx_directory *root,
|
fx_directory *root,
|
||||||
const fx_path *path,
|
fx_value path,
|
||||||
enum fx_file_mode mode,
|
enum fx_file_mode mode,
|
||||||
fx_file **out)
|
fx_file **out)
|
||||||
{
|
{
|
||||||
const fx_path *file_path = path;
|
|
||||||
unsigned int flags = fx_mode_to_unix_mode(mode);
|
unsigned int flags = fx_mode_to_unix_mode(mode);
|
||||||
|
|
||||||
if (flags == (unsigned int)-1) {
|
if (flags == (unsigned int)-1) {
|
||||||
@@ -422,16 +429,14 @@ fx_result fx_file_open(
|
|||||||
if (root) {
|
if (root) {
|
||||||
root_path = fx_directory_get_path(root);
|
root_path = fx_directory_get_path(root);
|
||||||
} else {
|
} else {
|
||||||
root_path = fx_path_create_cwd();
|
root_path = fx_path_get_system(FX_PATH_CWD);
|
||||||
free_root_path = true;
|
free_root_path = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fx_path *parts[] = {
|
const fx_value *parts[] = {};
|
||||||
root_path,
|
|
||||||
file_path,
|
|
||||||
};
|
|
||||||
|
|
||||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
fx_path *abs_path
|
||||||
|
= fx_path_join_list(2, &FX_VALUE_OBJECT(root_path), &path);
|
||||||
|
|
||||||
if (free_root_path) {
|
if (free_root_path) {
|
||||||
fx_path_unref((fx_path *)root_path);
|
fx_path_unref((fx_path *)root_path);
|
||||||
@@ -492,7 +497,7 @@ fx_result fx_file_open_temp(enum fx_file_mode mode, fx_file **out)
|
|||||||
|
|
||||||
fx_result status = fx_file_open(
|
fx_result status = fx_file_open(
|
||||||
FX_DIRECTORY_ROOT,
|
FX_DIRECTORY_ROOT,
|
||||||
rpath,
|
FX_VALUE_OBJECT(rpath),
|
||||||
mode | FX_FILE_CREATE_ONLY,
|
mode | FX_FILE_CREATE_ONLY,
|
||||||
out);
|
out);
|
||||||
|
|
||||||
|
|||||||
+60
-20
@@ -6,7 +6,6 @@
|
|||||||
#include <fx/io/file.h>
|
#include <fx/io/file.h>
|
||||||
#include <fx/io/path.h>
|
#include <fx/io/path.h>
|
||||||
#include <fx/string.h>
|
#include <fx/string.h>
|
||||||
#include <fx/value.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -41,7 +40,7 @@ static bool path_is_absolute(const struct fx_path_p *path)
|
|||||||
return s[0] == '/';
|
return s[0] == '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *path_get_cstr(const struct fx_path_p *path)
|
static const char *path_ptr(const struct fx_path_p *path)
|
||||||
{
|
{
|
||||||
return fx_string_get_cstr(path->p_pathstr);
|
return fx_string_get_cstr(path->p_pathstr);
|
||||||
}
|
}
|
||||||
@@ -51,7 +50,7 @@ static enum fx_status path_stat(
|
|||||||
struct fx_file_info *out)
|
struct fx_file_info *out)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int err = stat(path_get_cstr(path), &st);
|
int err = stat(path_ptr(path), &st);
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||||
@@ -92,22 +91,22 @@ static bool path_is_directory(const struct fx_path_p *path)
|
|||||||
return (info.attrib & FX_FILE_ATTRIB_DIRECTORY) != 0;
|
return (info.attrib & FX_FILE_ATTRIB_DIRECTORY) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void append_path(struct fx_path_p *dest, const struct fx_path_p *src)
|
static void append_path(struct fx_path_p *dest, const fx_string *src)
|
||||||
{
|
{
|
||||||
if (path_is_absolute(src)) {
|
const char *src_cstr = fx_string_get_cstr(src);
|
||||||
|
if (src_cstr[0] == '/') {
|
||||||
fx_string_clear(dest->p_pathstr);
|
fx_string_clear(dest->p_pathstr);
|
||||||
fx_string_append_s(dest->p_pathstr, src->p_pathstr);
|
fx_string_append_s(dest->p_pathstr, src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fx_string_get_size(dest->p_pathstr, FX_STRLEN_NORMAL) > 0
|
if (fx_string_get_size(dest->p_pathstr, FX_STRLEN_NORMAL) > 0
|
||||||
&& fx_string_get_last_char(dest->p_pathstr) != '/'
|
&& fx_string_get_last_char(dest->p_pathstr) != '/'
|
||||||
&& fx_string_get_first_char(src->p_pathstr) != '/') {
|
&& fx_string_get_first_char(src) != '/') {
|
||||||
char s[] = {'/', 0};
|
fx_string_append_c(dest->p_pathstr, '/');
|
||||||
fx_string_append_cstr(dest->p_pathstr, s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_string_append_s(dest->p_pathstr, src->p_pathstr);
|
fx_string_append_s(dest->p_pathstr, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fx_status path_unlink(const struct fx_path_p *path)
|
static enum fx_status path_unlink(const struct fx_path_p *path)
|
||||||
@@ -294,7 +293,7 @@ fx_path *fx_path_duplicate(const fx_path *path)
|
|||||||
return new_path;
|
return new_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_path *fx_path_join(const fx_path *paths[], size_t nr_paths)
|
fx_path *fx_path_join_array(const fx_value *values[], size_t nr_values)
|
||||||
{
|
{
|
||||||
fx_path *result = fx_path_create();
|
fx_path *result = fx_path_create();
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@@ -304,14 +303,53 @@ fx_path *fx_path_join(const fx_path *paths[], size_t nr_paths)
|
|||||||
struct fx_path_p *result_p
|
struct fx_path_p *result_p
|
||||||
= fx_object_get_private(result, FX_TYPE_PATH);
|
= fx_object_get_private(result, FX_TYPE_PATH);
|
||||||
|
|
||||||
for (size_t i = 0; i < nr_paths; i++) {
|
fx_stringstream *tmp = fx_stringstream_create();
|
||||||
if (paths[i]) {
|
fx_string *value_s = fx_string_create();
|
||||||
struct fx_path_p *path_p
|
for (size_t i = 0; i < nr_values; i++) {
|
||||||
= fx_object_get_private(paths[i], FX_TYPE_PATH);
|
if (!values[i]) {
|
||||||
append_path(result_p, path_p);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fx_stringstream_reset(tmp);
|
||||||
|
fx_value_to_string(values[i], tmp, NULL);
|
||||||
|
|
||||||
|
fx_string_clear(value_s);
|
||||||
|
fx_string_append_cstr(value_s, fx_stringstream_get_cstr(tmp));
|
||||||
|
append_path(result_p, value_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fx_string_unref(value_s);
|
||||||
|
fx_stringstream_unref(tmp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_path *fx_path_join_list(size_t count, ...)
|
||||||
|
{
|
||||||
|
fx_path *result = fx_path_create();
|
||||||
|
if (!result) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_path_p *result_p
|
||||||
|
= fx_object_get_private(result, FX_TYPE_PATH);
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, count);
|
||||||
|
|
||||||
|
fx_stringstream *tmp = fx_stringstream_create();
|
||||||
|
fx_string *value_s = fx_string_create();
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
const fx_value *value = va_arg(arg, const fx_value *);
|
||||||
|
|
||||||
|
fx_stringstream_reset(tmp);
|
||||||
|
fx_value_to_string(value, tmp, NULL);
|
||||||
|
|
||||||
|
fx_string_clear(value_s);
|
||||||
|
fx_string_append_cstr(value_s, fx_stringstream_get_cstr(tmp));
|
||||||
|
append_path(result_p, value_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_string_unref(value_s);
|
||||||
|
fx_stringstream_unref(tmp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +420,7 @@ enum fx_status fx_path_get_filename(const fx_path *path, fx_string *out_name)
|
|||||||
|
|
||||||
const char *fx_path_get_cstr(const fx_path *path)
|
const char *fx_path_get_cstr(const fx_path *path)
|
||||||
{
|
{
|
||||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_get_cstr, path);
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_ptr, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fx_path_length(const fx_path *path)
|
size_t fx_path_length(const fx_path *path)
|
||||||
@@ -402,7 +440,7 @@ static void path_init(fx_object *obj, void *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void path_fini(fx_object *obj, void *priv)
|
void path_fini(fx_object *obj, void *priv)
|
||||||
{
|
{
|
||||||
struct fx_path_p *path = priv;
|
struct fx_path_p *path = priv;
|
||||||
|
|
||||||
@@ -417,8 +455,10 @@ static fx_status path_to_string(
|
|||||||
struct fx_path_p *path
|
struct fx_path_p *path
|
||||||
= fx_object_get_private(obj->v_object, FX_TYPE_PATH);
|
= fx_object_get_private(obj->v_object, FX_TYPE_PATH);
|
||||||
|
|
||||||
fx_stream_write_cstr(out, fx_string_get_cstr(path->p_pathstr), NULL);
|
return fx_stream_write_cstr(
|
||||||
return FX_SUCCESS;
|
out,
|
||||||
|
fx_string_get_cstr(path->p_pathstr),
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** CLASS DEFINITION *********************************************************/
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|||||||
+4
-1
@@ -11,7 +11,10 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
fx_directory *dir;
|
fx_directory *dir;
|
||||||
fx_result result = fx_directory_open(
|
fx_result result = fx_directory_open(
|
||||||
NULL, FX_RV_PATH(path), FX_DIRECTORY_OPEN_CREATE_INTERMEDIATE, &dir);
|
NULL,
|
||||||
|
FX_CSTR(path),
|
||||||
|
FX_DIRECTORY_OPEN_CREATE_INTERMEDIATE,
|
||||||
|
&dir);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ int main(int argc, const char **argv)
|
|||||||
const char *path = argv[1];
|
const char *path = argv[1];
|
||||||
|
|
||||||
fx_directory *dir;
|
fx_directory *dir;
|
||||||
fx_result result = fx_directory_open(NULL, FX_RV_PATH(path), 0, &dir);
|
fx_result result = fx_directory_open(NULL, FX_CSTR(path), 0, &dir);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -6,10 +6,9 @@
|
|||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
fx_file *dest;
|
fx_file *dest;
|
||||||
fx_path *path = fx_path_create_from_cstr("data.txt");
|
|
||||||
fx_result result = fx_file_open(
|
fx_result result = fx_file_open(
|
||||||
NULL,
|
NULL,
|
||||||
path,
|
FX_CSTR("data.txt"),
|
||||||
FX_FILE_WRITE_ONLY | FX_FILE_CREATE,
|
FX_FILE_WRITE_ONLY | FX_FILE_CREATE,
|
||||||
&dest);
|
&dest);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
@@ -23,7 +22,6 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
printf("done. read %zu bytes total.\n", nr_read);
|
printf("done. read %zu bytes total.\n", nr_read);
|
||||||
|
|
||||||
fx_path_unref(path);
|
|
||||||
fx_file_unref(dest);
|
fx_file_unref(dest);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -12,17 +12,19 @@ int main(int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fx_directory *dir = NULL;
|
fx_directory *dir = NULL;
|
||||||
fx_path *path = fx_path_create_from_cstr(argv[1]);
|
fx_result result = fx_directory_open(
|
||||||
fx_result result = fx_directory_open(FX_DIRECTORY_ROOT, path, 0, &dir);
|
FX_DIRECTORY_ROOT,
|
||||||
|
FX_CSTR(argv[1]),
|
||||||
|
0,
|
||||||
|
&dir);
|
||||||
|
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_iterator *it = fx_directory_begin(
|
fx_iterator *it
|
||||||
dir,
|
= fx_directory_begin(dir, FX_DIRECTORY_ITERATE_PARENT_FIRST);
|
||||||
FX_DIRECTORY_ITERATE_PARENT_FIRST);
|
|
||||||
fx_foreach(val, it)
|
fx_foreach(val, it)
|
||||||
{
|
{
|
||||||
fx_directory_entry *entry = NULL;
|
fx_directory_entry *entry = NULL;
|
||||||
|
|||||||
+70
-27
@@ -1,6 +1,8 @@
|
|||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include "../../tty.h"
|
#include "../../tty.h"
|
||||||
|
|
||||||
#include <fx/encoding.h>
|
#include <ctype.h>
|
||||||
#include <fx/term/tty.h>
|
#include <fx/term/tty.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -102,11 +104,11 @@ static void init_tty(struct fx_tty *tty, FILE *in, FILE *out)
|
|||||||
|
|
||||||
tcgetattr(fd, &tty->t_ios_default);
|
tcgetattr(fd, &tty->t_ios_default);
|
||||||
memcpy(&tty->t_ios_raw, &tty->t_ios_default, sizeof tty->t_ios_raw);
|
memcpy(&tty->t_ios_raw, &tty->t_ios_default, sizeof tty->t_ios_raw);
|
||||||
|
setvbuf(out, NULL, _IOLBF, 4096);
|
||||||
|
|
||||||
tty->t_ios_raw.c_iflag &= ~(BRKINT | INPCK | ISTRIP | ICRNL | IXON);
|
tty->t_ios_raw.c_iflag &= ~(ICRNL | IXON);
|
||||||
tty->t_ios_raw.c_oflag &= ~(OPOST);
|
tty->t_ios_raw.c_oflag &= ~(OPOST);
|
||||||
tty->t_ios_raw.c_cflag |= (CS8);
|
tty->t_ios_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
|
||||||
tty->t_ios_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
|
||||||
|
|
||||||
tty->t_flags |= FX_TTY_INIT;
|
tty->t_flags |= FX_TTY_INIT;
|
||||||
}
|
}
|
||||||
@@ -207,6 +209,11 @@ void fx_tty_reset_vmode(struct fx_tty *tty)
|
|||||||
tty->t_vmode.v_attrib = FX_TTY_ATTRIB_NORMAL;
|
tty->t_vmode.v_attrib = FX_TTY_ATTRIB_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fx_tty_flush(struct fx_tty *tty)
|
||||||
|
{
|
||||||
|
fflush(tty->t_out);
|
||||||
|
}
|
||||||
|
|
||||||
static int compare_colour(
|
static int compare_colour(
|
||||||
const struct fx_tty_colour *a,
|
const struct fx_tty_colour *a,
|
||||||
const struct fx_tty_colour *b)
|
const struct fx_tty_colour *b)
|
||||||
@@ -408,24 +415,6 @@ void fx_tty_set_vmode(struct fx_tty *tty, const struct fx_tty_vmode *vmode)
|
|||||||
memcpy(&tty->t_vmode, vmode, sizeof *vmode);
|
memcpy(&tty->t_vmode, vmode, sizeof *vmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fx_keycode read_utf8(int fd, char header, int len)
|
|
||||||
{
|
|
||||||
char s[4] = {header, 0, 0, 0};
|
|
||||||
|
|
||||||
for (int i = 1; i < len; i++) {
|
|
||||||
char c;
|
|
||||||
int v = read(fd, &c, 1);
|
|
||||||
|
|
||||||
if (v != 1) {
|
|
||||||
return FX_KEY_EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
s[i] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fx_wchar_utf8_codepoint_decode(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
fx_keycode fx_tty_read_key(struct fx_tty *tty)
|
fx_keycode fx_tty_read_key(struct fx_tty *tty)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
@@ -450,11 +439,6 @@ fx_keycode fx_tty_read_key(struct fx_tty *tty)
|
|||||||
return FX_TTY_CTRL_KEY(c + 'a' - 1);
|
return FX_TTY_CTRL_KEY(c + 'a' - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int utf8_len = fx_wchar_utf8_header_decode(c);
|
|
||||||
if (utf8_len > 1) {
|
|
||||||
return read_utf8(fd, c, utf8_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c != 0x1b) {
|
if (c != 0x1b) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -590,3 +574,62 @@ enum fx_status fx_tty_get_dimensions(
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum fx_status fx_tty_get_cursor_position(
|
||||||
|
struct fx_tty *tty,
|
||||||
|
unsigned int *w,
|
||||||
|
unsigned int *h)
|
||||||
|
{
|
||||||
|
if (!(tty->t_flags & FX_TTY_INTERACTIVE)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int in_fd = fileno(tty->t_in);
|
||||||
|
int out_fd = fileno(tty->t_out);
|
||||||
|
|
||||||
|
write(out_fd, "\x1b[6n", 4);
|
||||||
|
|
||||||
|
char c;
|
||||||
|
read(in_fd, &c, 1);
|
||||||
|
read(in_fd, &c, 1);
|
||||||
|
|
||||||
|
char s[16] = {0};
|
||||||
|
for (int i = 0; i < sizeof s - 1; i++) {
|
||||||
|
read(in_fd, &c, 1);
|
||||||
|
if (!isdigit(c)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s[i] = c;
|
||||||
|
s[i + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w) {
|
||||||
|
if (s[0]) {
|
||||||
|
*w = atoi(s);
|
||||||
|
} else {
|
||||||
|
*w = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s[0] = 0;
|
||||||
|
for (int i = 0; i < sizeof s - 1; i++) {
|
||||||
|
read(in_fd, &c, 1);
|
||||||
|
if (!isdigit(c)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s[i] = c;
|
||||||
|
s[i + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h) {
|
||||||
|
if (s[0]) {
|
||||||
|
*h = atoi(s);
|
||||||
|
} else {
|
||||||
|
*h = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
+283
@@ -0,0 +1,283 @@
|
|||||||
|
#include <fx/bytestream.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define DEFAULT_CAPACITY 128
|
||||||
|
|
||||||
|
/*** PRIVATE DATA *************************************************************/
|
||||||
|
|
||||||
|
struct fx_bytestream_p {
|
||||||
|
unsigned char *s_buf;
|
||||||
|
size_t s_ptr;
|
||||||
|
size_t s_len;
|
||||||
|
size_t s_max;
|
||||||
|
unsigned char s_alloc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static enum fx_status __gets(
|
||||||
|
struct fx_bytestream_p *s,
|
||||||
|
unsigned char *buf,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_read)
|
||||||
|
{
|
||||||
|
size_t available = s->s_len - s->s_ptr;
|
||||||
|
size_t to_copy = len;
|
||||||
|
|
||||||
|
if (available < to_copy) {
|
||||||
|
to_copy = available;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, s->s_buf + s->s_ptr, to_copy);
|
||||||
|
|
||||||
|
s->s_ptr += to_copy;
|
||||||
|
|
||||||
|
if (s->s_ptr == s->s_len) {
|
||||||
|
s->s_ptr = s->s_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nr_read) {
|
||||||
|
*nr_read = to_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fx_status __puts(
|
||||||
|
struct fx_bytestream_p *s,
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t len,
|
||||||
|
size_t *nr_written)
|
||||||
|
{
|
||||||
|
size_t available = s->s_max - s->s_len;
|
||||||
|
size_t to_copy = len;
|
||||||
|
|
||||||
|
if (to_copy > available && s->s_alloc == 1) {
|
||||||
|
unsigned char *new_buf
|
||||||
|
= realloc(s->s_buf, s->s_len + to_copy + 1);
|
||||||
|
if (!new_buf) {
|
||||||
|
return FX_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->s_buf = new_buf;
|
||||||
|
s->s_max = s->s_len + to_copy;
|
||||||
|
available = s->s_max - s->s_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (available < to_copy) {
|
||||||
|
to_copy = available;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(s->s_buf + s->s_len, buf, to_copy);
|
||||||
|
s->s_buf[s->s_len + to_copy] = 0;
|
||||||
|
|
||||||
|
/* increment the length by the full byte length, even if only a
|
||||||
|
* portion was copied */
|
||||||
|
s->s_len += len;
|
||||||
|
|
||||||
|
if (nr_written) {
|
||||||
|
*nr_written = to_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fx_status bytestream_reset(struct fx_bytestream_p *s)
|
||||||
|
{
|
||||||
|
s->s_len = 0;
|
||||||
|
|
||||||
|
if (s->s_buf) {
|
||||||
|
*s->s_buf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t bytestream_get_length(const struct fx_bytestream_p *strv)
|
||||||
|
{
|
||||||
|
return strv->s_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned char *bytestream_get_ptr(const struct fx_bytestream_p *s)
|
||||||
|
{
|
||||||
|
return s->s_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char *bytestream_steal(struct fx_bytestream_p *s)
|
||||||
|
{
|
||||||
|
unsigned char *out = s->s_buf;
|
||||||
|
|
||||||
|
memset(s, 0x0, sizeof *s);
|
||||||
|
|
||||||
|
s->s_alloc = 1;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
fx_bytestream *fx_bytestream_create_view(unsigned char *buf, size_t max)
|
||||||
|
{
|
||||||
|
fx_bytestream *s = fx_object_create(FX_TYPE_BYTESTREAM);
|
||||||
|
if (!s) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_stream_cfg *cfg = fx_object_get_protected(s, FX_TYPE_STREAM);
|
||||||
|
struct fx_bytestream_p *p
|
||||||
|
= fx_object_get_private(s, FX_TYPE_BYTESTREAM);
|
||||||
|
|
||||||
|
cfg->s_mode = FX_STREAM_READ | FX_STREAM_WRITE | FX_STREAM_BINARY
|
||||||
|
| Z__FX_STREAM_STATIC;
|
||||||
|
|
||||||
|
p->s_buf = buf;
|
||||||
|
p->s_max = max;
|
||||||
|
p->s_len = max;
|
||||||
|
p->s_alloc = 0;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_bytestream *fx_bytestream_create_readonly_view(
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t max)
|
||||||
|
{
|
||||||
|
fx_bytestream *s = fx_object_create(FX_TYPE_BYTESTREAM);
|
||||||
|
if (!s) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_stream_cfg *cfg = fx_object_get_protected(s, FX_TYPE_STREAM);
|
||||||
|
struct fx_bytestream_p *p
|
||||||
|
= fx_object_get_private(s, FX_TYPE_BYTESTREAM);
|
||||||
|
|
||||||
|
cfg->s_mode = FX_STREAM_READ | FX_STREAM_BINARY | Z__FX_STREAM_STATIC;
|
||||||
|
|
||||||
|
p->s_buf = (unsigned char *)buf;
|
||||||
|
p->s_max = max;
|
||||||
|
p->s_len = max;
|
||||||
|
p->s_alloc = 0;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_bytestream *fx_bytestream_create(void)
|
||||||
|
{
|
||||||
|
fx_bytestream *s = fx_object_create(FX_TYPE_BYTESTREAM);
|
||||||
|
if (!s) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_stream_cfg *cfg = fx_object_get_protected(s, FX_TYPE_STREAM);
|
||||||
|
struct fx_bytestream_p *p
|
||||||
|
= fx_object_get_private(s, FX_TYPE_BYTESTREAM);
|
||||||
|
|
||||||
|
cfg->s_mode = FX_STREAM_READ | FX_STREAM_WRITE | FX_STREAM_BINARY
|
||||||
|
| Z__FX_STREAM_STATIC;
|
||||||
|
|
||||||
|
p->s_buf = malloc(DEFAULT_CAPACITY + 1);
|
||||||
|
if (!p->s_buf) {
|
||||||
|
fx_bytestream_unref(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(p->s_buf, 0x0, DEFAULT_CAPACITY + 1);
|
||||||
|
p->s_max = DEFAULT_CAPACITY;
|
||||||
|
p->s_len = 0;
|
||||||
|
p->s_alloc = 1;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fx_bytestream_get_length(const fx_bytestream *strv)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(
|
||||||
|
FX_TYPE_BYTESTREAM,
|
||||||
|
bytestream_get_length,
|
||||||
|
strv);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum fx_status fx_bytestream_reset(fx_bytestream *strv)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_BYTESTREAM, bytestream_reset, strv);
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char *fx_bytestream_get_ptr(const fx_bytestream *s)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_BYTESTREAM, bytestream_get_ptr, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *fx_bytestream_steal(fx_bytestream *s)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_BYTESTREAM, bytestream_steal, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static void bytestream_init(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
struct fx_bytestream_p *stream = priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bytestream_fini(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
struct fx_bytestream_p *stream = priv;
|
||||||
|
|
||||||
|
if (stream->s_alloc && stream->s_buf) {
|
||||||
|
free(stream->s_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fx_status stream_read(
|
||||||
|
fx_stream *stream,
|
||||||
|
void *buf,
|
||||||
|
size_t count,
|
||||||
|
size_t *nr_read)
|
||||||
|
{
|
||||||
|
struct fx_bytestream_p *s
|
||||||
|
= fx_object_get_private(stream, FX_TYPE_BYTESTREAM);
|
||||||
|
|
||||||
|
enum fx_status status = __gets(s, buf, count, nr_read);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum fx_status stream_write(
|
||||||
|
fx_stream *stream,
|
||||||
|
const void *buf,
|
||||||
|
size_t count,
|
||||||
|
size_t *nr_written)
|
||||||
|
{
|
||||||
|
struct fx_bytestream_p *s
|
||||||
|
= fx_object_get_private(stream, FX_TYPE_BYTESTREAM);
|
||||||
|
|
||||||
|
enum fx_status status
|
||||||
|
= __puts(s, (const unsigned char *)buf, count, nr_written);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_BEGIN(fx_bytestream)
|
||||||
|
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_stream, FX_TYPE_STREAM)
|
||||||
|
FX_INTERFACE_ENTRY(s_close) = NULL;
|
||||||
|
FX_INTERFACE_ENTRY(s_seek) = NULL;
|
||||||
|
FX_INTERFACE_ENTRY(s_tell) = NULL;
|
||||||
|
FX_INTERFACE_ENTRY(s_getc) = NULL;
|
||||||
|
FX_INTERFACE_ENTRY(s_read) = stream_read;
|
||||||
|
FX_INTERFACE_ENTRY(s_write) = stream_write;
|
||||||
|
FX_INTERFACE_ENTRY(s_reserve) = NULL;
|
||||||
|
FX_TYPE_VTABLE_INTERFACE_END(fx_stream, FX_TYPE_STREAM)
|
||||||
|
FX_TYPE_CLASS_END(fx_bytestream)
|
||||||
|
|
||||||
|
FX_TYPE_DEFINITION_BEGIN(fx_bytestream)
|
||||||
|
FX_TYPE_ID(0xdcb7fb3a, 0xc476, 0x4c0b, 0xad5a, 0x039d1190a5b7);
|
||||||
|
FX_TYPE_EXTENDS(FX_TYPE_STREAM);
|
||||||
|
FX_TYPE_CLASS(fx_bytestream_class);
|
||||||
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_bytestream_p);
|
||||||
|
FX_TYPE_INSTANCE_INIT(bytestream_init);
|
||||||
|
FX_TYPE_INSTANCE_FINI(bytestream_fini);
|
||||||
|
FX_TYPE_DEFINITION_END(fx_bytestream)
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef FX_CORE_BYTESTREAM_H_
|
||||||
|
#define FX_CORE_BYTESTREAM_H_
|
||||||
|
|
||||||
|
#include <fx/macros.h>
|
||||||
|
#include <fx/misc.h>
|
||||||
|
#include <fx/status.h>
|
||||||
|
#include <fx/stream.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
FX_DECLS_BEGIN;
|
||||||
|
|
||||||
|
#define FX_TYPE_BYTESTREAM (fx_bytestream_get_type())
|
||||||
|
|
||||||
|
FX_DECLARE_TYPE(fx_bytestream);
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_bytestream)
|
||||||
|
FX_TYPE_CLASS_DECLARATION_END(fx_bytestream)
|
||||||
|
|
||||||
|
FX_API fx_type_id fx_bytestream_get_type(void);
|
||||||
|
|
||||||
|
FX_API fx_bytestream *fx_bytestream_create(void);
|
||||||
|
FX_API fx_bytestream *fx_bytestream_create_view(unsigned char *buf, size_t max);
|
||||||
|
FX_API fx_bytestream *fx_bytestream_create_readonly_view(
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t max);
|
||||||
|
|
||||||
|
FX_API fx_status fx_bytestream_reset(fx_bytestream *strv);
|
||||||
|
|
||||||
|
FX_API const unsigned char *fx_bytestream_get_ptr(const fx_bytestream *strv);
|
||||||
|
FX_API unsigned char *fx_bytestream_steal(fx_bytestream *strv);
|
||||||
|
|
||||||
|
FX_API size_t fx_bytestream_get_length(const fx_bytestream *strv);
|
||||||
|
FX_API size_t fx_bytestream_get_available(const fx_bytestream *strv);
|
||||||
|
|
||||||
|
FX_DECLS_END;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -22,6 +22,7 @@ typedef struct _fx_object_class {
|
|||||||
FX_TYPE_FWDREF(fx_stream) *,
|
FX_TYPE_FWDREF(fx_stream) *,
|
||||||
const char *);
|
const char *);
|
||||||
fx_status (*hash)(const struct fx_value *, uint64_t *);
|
fx_status (*hash)(const struct fx_value *, uint64_t *);
|
||||||
|
fx_status (*clone)(const struct fx_value *, struct fx_value *);
|
||||||
} fx_object_class;
|
} fx_object_class;
|
||||||
|
|
||||||
FX_API fx_type_id fx_object_get_type(void);
|
FX_API fx_type_id fx_object_get_type(void);
|
||||||
@@ -46,6 +47,7 @@ FX_API fx_status fx_object_to_string(
|
|||||||
const fx_object *p,
|
const fx_object *p,
|
||||||
FX_TYPE_FWDREF(fx_stream) * out,
|
FX_TYPE_FWDREF(fx_stream) * out,
|
||||||
const char *format);
|
const char *format);
|
||||||
|
FX_API fx_status fx_object_clone(const fx_object *src, fx_object **dest);
|
||||||
FX_API bool fx_object_is_type(const fx_object *p, fx_type_id type);
|
FX_API bool fx_object_is_type(const fx_object *p, fx_type_id type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+18
-1
@@ -23,7 +23,7 @@ FX_TYPE_DEFINITION_END(fx_object)
|
|||||||
|
|
||||||
fx_type_id fx_object_query_type(const struct _fx_object *obj)
|
fx_type_id fx_object_query_type(const struct _fx_object *obj)
|
||||||
{
|
{
|
||||||
return &obj->obj_type->ty_id;
|
return obj ? &obj->obj_type->ty_id : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_result fx_object_instantiate(
|
fx_result fx_object_instantiate(
|
||||||
@@ -98,6 +98,23 @@ fx_status fx_object_to_string(
|
|||||||
return FX_SUCCESS;
|
return FX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fx_status fx_object_clone(const fx_object *src, fx_object **dest)
|
||||||
|
{
|
||||||
|
fx_object_class *iface = fx_object_get_interface(src, FX_TYPE_OBJECT);
|
||||||
|
fx_value dest_v = FX_VALUE_EMPTY;
|
||||||
|
if (!iface || !iface->clone) {
|
||||||
|
return FX_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_status status = iface->clone(&FX_VALUE_OBJECT(src), &dest_v);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_value_get_object(&dest_v, dest);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
bool fx_object_is_type(const struct _fx_object *p, fx_type_id type)
|
bool fx_object_is_type(const struct _fx_object *p, fx_type_id type)
|
||||||
{
|
{
|
||||||
if (!p) {
|
if (!p) {
|
||||||
|
|||||||
+3
-3
@@ -11,11 +11,11 @@ int main(int argc, const char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *path_cstr = argv[1];
|
const char *path = argv[1];
|
||||||
fx_path *path = fx_path_create_from_cstr(path_cstr);
|
|
||||||
|
|
||||||
fx_file *src = NULL;
|
fx_file *src = NULL;
|
||||||
fx_result result = fx_file_open(NULL, path, FX_FILE_READ_ONLY, &src);
|
fx_result result
|
||||||
|
= fx_file_open(NULL, FX_CSTR(path), FX_FILE_READ_ONLY, &src);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
+3
-3
@@ -11,11 +11,11 @@ int main(int argc, const char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *path_cstr = argv[1];
|
const char *path = argv[1];
|
||||||
fx_path *path = fx_path_create_from_cstr(path_cstr);
|
|
||||||
|
|
||||||
fx_file *src = NULL;
|
fx_file *src = NULL;
|
||||||
fx_result result = fx_file_open(NULL, path, FX_FILE_READ_ONLY, &src);
|
fx_result result
|
||||||
|
= fx_file_open(NULL, FX_CSTR(path), FX_FILE_READ_ONLY, &src);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
+3
-3
@@ -9,11 +9,11 @@ int main(int argc, const char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *path_cstr = argv[1];
|
const char *path = argv[1];
|
||||||
fx_path *path = fx_path_create_from_cstr(path_cstr);
|
|
||||||
|
|
||||||
fx_file *src = NULL;
|
fx_file *src = NULL;
|
||||||
fx_result result = fx_file_open(NULL, path, FX_FILE_READ_ONLY, &src);
|
fx_result result
|
||||||
|
= fx_file_open(NULL, FX_CSTR(path), FX_FILE_READ_ONLY, &src);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
+3
-3
@@ -10,11 +10,11 @@ int main(int argc, const char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *path_cstr = argv[1];
|
const char *path = argv[1];
|
||||||
fx_path *path = fx_path_create_from_cstr(path_cstr);
|
|
||||||
|
|
||||||
fx_file *src = NULL;
|
fx_file *src = NULL;
|
||||||
fx_result result = fx_file_open(NULL, path, FX_FILE_READ_ONLY, &src);
|
fx_result result
|
||||||
|
= fx_file_open(NULL, FX_CSTR(path), FX_FILE_READ_ONLY, &src);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user