Compare commits
16 Commits
912c450e6e
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b072632499 | |||
| 15a9147e15 | |||
| d24592dde4 | |||
| ce56eacafe | |||
| dbf50395d0 | |||
| 4aaa165e5f | |||
| 4fcbcfdfb2 | |||
| cb39baa233 | |||
| 5646c8c2b8 | |||
| 3529e8525a | |||
| 6a26e00438 | |||
| c76008e498 | |||
| 321622ac16 | |||
| c39f50a0ee | |||
| 5ab348fd30 | |||
| 709d11331c |
+63
-5
@@ -1,7 +1,7 @@
|
||||
BasedOnStyle: WebKit
|
||||
IndentWidth: 8
|
||||
---
|
||||
Language: Cpp
|
||||
Language: C
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
ColumnLimit: 80
|
||||
@@ -26,8 +26,8 @@ AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: OnePerLine
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
BitFieldColonSpacing: Both
|
||||
BreakBeforeBraces: Linux
|
||||
@@ -47,7 +47,7 @@ SpacesBeforeTrailingComments: 3
|
||||
TabWidth: 8
|
||||
UseTab: AlignWithSpaces
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||
PenaltyExcessCharacter: 5
|
||||
PenaltyExcessCharacter: 999999999
|
||||
PenaltyBreakOpenParenthesis: 5
|
||||
PenaltyBreakBeforeFirstCallParameter: 5
|
||||
PenaltyIndentedWhitespace: 0
|
||||
@@ -84,7 +84,7 @@ AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: true
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
BitFieldColonSpacing: Both
|
||||
@@ -116,3 +116,61 @@ ForEachMacros:
|
||||
- fx_queue_foreach
|
||||
MacroBlockBegin: "FX_TYPE_.*_BEGIN"
|
||||
MacroBlockEnd: "FX_TYPE_.*_END"
|
||||
---
|
||||
Language: Cpp
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Right
|
||||
ColumnLimit: 80
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: AlignAfterOperator
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: OnePerLine
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
BitFieldColonSpacing: Both
|
||||
BreakBeforeBraces: Linux
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakStringLiterals: true
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: true
|
||||
IncludeBlocks: Regroup
|
||||
SortIncludes: true
|
||||
IndentRequires: true
|
||||
NamespaceIndentation: Inner
|
||||
ReflowComments: true
|
||||
SpacesBeforeTrailingComments: 3
|
||||
TabWidth: 8
|
||||
UseTab: AlignWithSpaces
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||
PenaltyExcessCharacter: 9999999
|
||||
PenaltyBreakOpenParenthesis: 5
|
||||
PenaltyBreakBeforeFirstCallParameter: 5
|
||||
PenaltyIndentedWhitespace: 0
|
||||
AttributeMacros:
|
||||
- FX_API
|
||||
ForEachMacros:
|
||||
- fx_btree_foreach
|
||||
- fx_queue_foreach
|
||||
MacroBlockBegin: "FX_TYPE_.*_BEGIN"
|
||||
MacroBlockEnd: "FX_TYPE_.*_END"
|
||||
|
||||
+3
-3
@@ -322,8 +322,8 @@ static fx_status parse_short_opt(struct argv_parser *parser)
|
||||
parser->cmd, NULL, parser->arglist);
|
||||
fx_err("unrecognised argument '" F_YELLOW "-%c" F_RESET
|
||||
"'\n\n",
|
||||
flag, fx_string_ptr(usage));
|
||||
fx_i("usage: %s", fx_string_ptr(usage));
|
||||
flag, fx_string_get_cstr(usage));
|
||||
fx_i("usage: %s", fx_string_get_cstr(usage));
|
||||
fx_i("for more information, use '" F_YELLOW
|
||||
"--help" F_RESET "'\n");
|
||||
fx_string_unref(usage);
|
||||
@@ -452,7 +452,7 @@ static fx_status parse_long_opt(struct argv_parser *parser)
|
||||
fx_err("unrecognised argument '" F_YELLOW "--%s" F_RESET
|
||||
"'\n\nusage: %s\n\nfor more information, use '" F_YELLOW
|
||||
"--help" F_RESET "'\n",
|
||||
opt_name, fx_string_ptr(usage));
|
||||
opt_name, fx_string_get_cstr(usage));
|
||||
fx_string_unref(usage);
|
||||
|
||||
return FX_ERR_NO_ENTRY;
|
||||
|
||||
+8
-8
@@ -631,7 +631,7 @@ static void print_options_list(struct fx_command *cmd)
|
||||
}
|
||||
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, " ");
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, fx_string_ptr(opt_str));
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, fx_string_get_cstr(opt_str));
|
||||
|
||||
if (new_paragraph) {
|
||||
format.p_flags = 0;
|
||||
@@ -650,7 +650,7 @@ static void print_options_list(struct fx_command *cmd)
|
||||
len++;
|
||||
}
|
||||
|
||||
fx_print_paragraph(fx_string_ptr(desc_str), OUTPUT_STREAM, &format);
|
||||
fx_print_paragraph(fx_string_get_cstr(desc_str), OUTPUT_STREAM, &format);
|
||||
|
||||
if (new_paragraph) {
|
||||
fx_tty_putc(OUTPUT_STREAM, 0, '\n');
|
||||
@@ -704,7 +704,7 @@ static void print_args_list(struct fx_command *cmd)
|
||||
z__fx_get_arg_usage_string(arg, true, str);
|
||||
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, " ");
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, fx_string_ptr(str));
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, fx_string_get_cstr(str));
|
||||
unsigned int len = fx_string_get_size(
|
||||
str, FX_STRLEN_IGNORE_ESC
|
||||
| FX_STRLEN_IGNORE_MOD)
|
||||
@@ -717,7 +717,7 @@ static void print_args_list(struct fx_command *cmd)
|
||||
fx_string_clear(str);
|
||||
z__fx_get_arg_description(arg, str);
|
||||
|
||||
fx_print_paragraph(fx_string_ptr(str), OUTPUT_STREAM, &format);
|
||||
fx_print_paragraph(fx_string_get_cstr(str), OUTPUT_STREAM, &format);
|
||||
entry = fx_queue_next(entry);
|
||||
}
|
||||
|
||||
@@ -764,7 +764,7 @@ static void print_commands_list(struct fx_command *cmd)
|
||||
get_command_string(sub, str);
|
||||
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, " ");
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, fx_string_ptr(str));
|
||||
fx_tty_puts(OUTPUT_STREAM, 0, fx_string_get_cstr(str));
|
||||
unsigned int len = fx_string_get_size(
|
||||
str, FX_STRLEN_IGNORE_ESC
|
||||
| FX_STRLEN_IGNORE_MOD)
|
||||
@@ -777,7 +777,7 @@ static void print_commands_list(struct fx_command *cmd)
|
||||
fx_string_clear(str);
|
||||
get_command_description(sub, str);
|
||||
|
||||
fx_print_paragraph(fx_string_ptr(str), OUTPUT_STREAM, &format);
|
||||
fx_print_paragraph(fx_string_get_cstr(str), OUTPUT_STREAM, &format);
|
||||
|
||||
entry = fx_queue_next(entry);
|
||||
}
|
||||
@@ -941,7 +941,7 @@ static void print_usage(struct fx_command *cmd, struct fx_arglist *args)
|
||||
if (fx_queue_empty(&cmd->c_usage)) {
|
||||
fx_string *usage
|
||||
= z__fx_command_default_usage_string(cmd, NULL, args);
|
||||
fx_print_paragraph(fx_string_ptr(usage), OUTPUT_STREAM, &format);
|
||||
fx_print_paragraph(fx_string_get_cstr(usage), OUTPUT_STREAM, &format);
|
||||
fx_string_unref(usage);
|
||||
return;
|
||||
}
|
||||
@@ -954,7 +954,7 @@ static void print_usage(struct fx_command *cmd, struct fx_arglist *args)
|
||||
|
||||
fx_string_clear(str);
|
||||
get_usage_string(cmd, args, usage, str);
|
||||
fx_print_paragraph(fx_string_ptr(str), OUTPUT_STREAM, &format);
|
||||
fx_print_paragraph(fx_string_get_cstr(str), OUTPUT_STREAM, &format);
|
||||
|
||||
entry = fx_queue_next(entry);
|
||||
}
|
||||
|
||||
+8
-8
@@ -45,7 +45,7 @@ enum fx_status fx_arglist_report_missing_option(
|
||||
|
||||
fx_err("required option `" F_YELLOW "%s" F_RESET "` was not specified.",
|
||||
fx_stringstream_ptr(opt_name));
|
||||
fx_i("usage: %s", fx_string_ptr(opt_string));
|
||||
fx_i("usage: %s", fx_string_get_cstr(opt_string));
|
||||
fx_i("for more information, use `" F_YELLOW "--help" F_RESET "`");
|
||||
|
||||
fx_string_unref(opt_string);
|
||||
@@ -61,7 +61,7 @@ enum fx_status fx_arglist_report_unexpected_arg(
|
||||
args->list_command, NULL, args);
|
||||
|
||||
fx_err("unexpected argument '" F_YELLOW "%s" F_RESET "' found.", value);
|
||||
fx_i("usage: %s", fx_string_ptr(usage));
|
||||
fx_i("usage: %s", fx_string_get_cstr(usage));
|
||||
fx_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
||||
|
||||
return FX_SUCCESS;
|
||||
@@ -95,16 +95,16 @@ enum fx_status fx_arglist_report_invalid_arg_value(
|
||||
|
||||
fx_err("invalid value '" F_YELLOW "%s" F_RESET "' for '" F_YELLOW
|
||||
"%s" F_RESET "'.",
|
||||
value, fx_string_ptr(opt_string));
|
||||
value, fx_string_get_cstr(opt_string));
|
||||
|
||||
if (opt) {
|
||||
fx_i("'" F_YELLOW "%s" F_RESET
|
||||
"' accepts the following values for '" F_YELLOW "%s" F_RESET
|
||||
"':",
|
||||
fx_string_ptr(opt_string), arg->arg_name);
|
||||
fx_string_get_cstr(opt_string), arg->arg_name);
|
||||
} else {
|
||||
fx_i("'" F_YELLOW "%s" F_RESET "' accepts the following values:",
|
||||
fx_string_ptr(opt_string));
|
||||
fx_string_get_cstr(opt_string));
|
||||
}
|
||||
|
||||
for (int i = 0; arg->arg_allowed_values[i]; i++) {
|
||||
@@ -114,7 +114,7 @@ enum fx_status fx_arglist_report_invalid_arg_value(
|
||||
}
|
||||
|
||||
fx_printf("\n");
|
||||
fx_i("usage: %s", fx_string_ptr(usage));
|
||||
fx_i("usage: %s", fx_string_get_cstr(usage));
|
||||
fx_i("for more information, use '" F_YELLOW "--help" F_RESET);
|
||||
|
||||
fx_string_unref(usage);
|
||||
@@ -183,9 +183,9 @@ enum fx_status fx_arglist_report_missing_args(
|
||||
|
||||
fx_err("argument `" F_YELLOW "%s" F_RESET "` requires " F_GREEN_BOLD
|
||||
"%s" F_RESET " `" F_YELLOW "%s" F_RESET "` value%s, but %s.",
|
||||
fx_string_ptr(opt_string), required_arg_count, arg->arg_name,
|
||||
fx_string_get_cstr(opt_string), required_arg_count, arg->arg_name,
|
||||
(arg->arg_nr_values == 1) ? "" : "s", supplied_arg_str);
|
||||
fx_i("usage: %s", fx_string_ptr(usage));
|
||||
fx_i("usage: %s", fx_string_get_cstr(usage));
|
||||
fx_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
|
||||
|
||||
fx_string_unref(usage);
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
bool fx_wchar_is_number(fx_wchar c)
|
||||
{
|
||||
return iswnumber((wchar_t)c);
|
||||
return iswdigit((wchar_t)c);
|
||||
}
|
||||
|
||||
bool fx_wchar_is_alpha(fx_wchar c)
|
||||
|
||||
+4
-4
@@ -756,18 +756,18 @@ static void get_error_id(
|
||||
fx_stringstream *id = fx_stringstream_create_with_buffer(out, max);
|
||||
|
||||
if (vendor_name) {
|
||||
fx_stream_write_string(id, vendor_name, NULL);
|
||||
fx_stream_write_cstr(id, vendor_name, NULL);
|
||||
}
|
||||
|
||||
if (error_name) {
|
||||
if (vendor_name) {
|
||||
fx_stream_write_string(id, ".", NULL);
|
||||
fx_stream_write_cstr(id, ".", NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_string(id, error_name, NULL);
|
||||
fx_stream_write_cstr(id, error_name, NULL);
|
||||
} else {
|
||||
if (vendor_name) {
|
||||
fx_stream_write_string(id, "#", NULL);
|
||||
fx_stream_write_cstr(id, "#", NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_fmt(id, NULL, "%ld", code);
|
||||
|
||||
@@ -84,7 +84,7 @@ FX_API fx_status fx_stream_read_all_bytes_s(
|
||||
fx_stream *src, fx_stream *dest, fx_stream_buffer *buffer, size_t *nr_read);
|
||||
|
||||
FX_API fx_status fx_stream_write_char(fx_stream *stream, fx_wchar c);
|
||||
FX_API fx_status fx_stream_write_string(
|
||||
FX_API fx_status fx_stream_write_cstr(
|
||||
fx_stream *stream, const char *s, size_t *nr_written);
|
||||
|
||||
FX_API fx_status fx_stream_write_bytes(
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ static void to_stream(const struct fx_rope *rope, void *arg)
|
||||
case FX_ROPE_F_CSTR:
|
||||
case FX_ROPE_F_CSTR_BORROWED:
|
||||
case FX_ROPE_F_CSTR_STATIC:
|
||||
fx_stream_write_string(out, rope->r_v.v_cstr.s, NULL);
|
||||
fx_stream_write_cstr(out, rope->r_v.v_cstr.s, NULL);
|
||||
break;
|
||||
case FX_ROPE_F_INT:
|
||||
fx_stream_write_fmt(out, NULL, "%" PRIdPTR, rope->r_v.v_int);
|
||||
|
||||
+140
-42
@@ -84,12 +84,17 @@ static enum fx_status stdio_write(fx_stream *, const void *, size_t, size_t *);
|
||||
static enum fx_status stdio_seek(fx_stream *, long long, fx_stream_seek_origin);
|
||||
static enum fx_status stdio_tell(const fx_stream *, size_t *);
|
||||
|
||||
static enum fx_status stream_get_data(const fx_stream *strp, struct stream_data *out)
|
||||
static enum fx_status stream_get_data(
|
||||
const fx_stream *strp,
|
||||
struct stream_data *out)
|
||||
{
|
||||
out->s_obj = (fx_stream *)strp;
|
||||
return fx_object_get_data(
|
||||
strp, FX_TYPE_STREAM, (void **)&out->s_private,
|
||||
(void **)&out->s_cfg, (void **)&out->s_ops);
|
||||
strp,
|
||||
FX_TYPE_STREAM,
|
||||
(void **)&out->s_private,
|
||||
(void **)&out->s_cfg,
|
||||
(void **)&out->s_ops);
|
||||
}
|
||||
|
||||
static int current_indent(struct stream_data *stream)
|
||||
@@ -117,7 +122,9 @@ static size_t stream_cursor(const struct stream_data *stream)
|
||||
}
|
||||
|
||||
static enum fx_status stream_seek(
|
||||
struct stream_data *stream, long long offset, fx_stream_seek_origin origin)
|
||||
struct stream_data *stream,
|
||||
long long offset,
|
||||
fx_stream_seek_origin origin)
|
||||
{
|
||||
if (!stream || !stream->s_ops || !stream->s_ops->s_seek) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -236,7 +243,8 @@ static enum fx_status __write_char(struct stream_data *stream, fx_wchar c)
|
||||
}
|
||||
}
|
||||
|
||||
status = stream->s_ops->s_write(stream->s_obj, (unsigned char *)s, len, &w);
|
||||
status = stream->s_ops
|
||||
->s_write(stream->s_obj, (unsigned char *)s, len, &w);
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
return status;
|
||||
@@ -289,7 +297,10 @@ static enum fx_status stream_write_char(struct stream_data *stream, fx_wchar c)
|
||||
}
|
||||
|
||||
static enum fx_status stream_read_bytes(
|
||||
struct stream_data *stream, void *buf, size_t count, size_t *nr_read)
|
||||
struct stream_data *stream,
|
||||
void *buf,
|
||||
size_t count,
|
||||
size_t *nr_read)
|
||||
{
|
||||
if (!(stream->s_cfg->s_mode & FX_STREAM_READ)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -304,7 +315,10 @@ static enum fx_status stream_read_bytes(
|
||||
return stream->s_ops->s_read(stream->s_obj, buf, count, nr_read);
|
||||
}
|
||||
|
||||
static enum fx_status stream_read_line(struct stream_data *stream, char *s, size_t max)
|
||||
static enum fx_status stream_read_line(
|
||||
struct stream_data *stream,
|
||||
char *s,
|
||||
size_t max)
|
||||
{
|
||||
if (!(stream->s_cfg->s_mode & FX_STREAM_READ)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -337,7 +351,8 @@ static enum fx_status stream_read_line(struct stream_data *stream, char *s, size
|
||||
}
|
||||
|
||||
static enum fx_status stream_read_line_s(
|
||||
struct stream_data *src, struct stream_data *dest)
|
||||
struct stream_data *src,
|
||||
struct stream_data *dest)
|
||||
{
|
||||
if (!(src->s_cfg->s_mode & FX_STREAM_READ)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -374,7 +389,8 @@ static enum fx_status stream_read_line_s(
|
||||
}
|
||||
|
||||
static enum fx_status stream_read_line_to_bstr(
|
||||
struct stream_data *src, struct fx_bstr *dest)
|
||||
struct stream_data *src,
|
||||
struct fx_bstr *dest)
|
||||
{
|
||||
if (!(src->s_cfg->s_mode & FX_STREAM_READ)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -407,7 +423,10 @@ static enum fx_status stream_read_line_to_bstr(
|
||||
}
|
||||
|
||||
static enum fx_status stream_write_bytes(
|
||||
struct stream_data *stream, const void *buf, size_t count, size_t *nr_written)
|
||||
struct stream_data *stream,
|
||||
const void *buf,
|
||||
size_t count,
|
||||
size_t *nr_written)
|
||||
{
|
||||
if (!(stream->s_cfg->s_mode & FX_STREAM_WRITE)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -423,7 +442,10 @@ static enum fx_status stream_write_bytes(
|
||||
}
|
||||
|
||||
static enum fx_status stream_read_all_bytes(
|
||||
struct stream_data *stream, void *p, size_t max, size_t *out_nr_read)
|
||||
struct stream_data *stream,
|
||||
void *p,
|
||||
size_t max,
|
||||
size_t *out_nr_read)
|
||||
{
|
||||
if (!(stream->s_cfg->s_mode & FX_STREAM_READ)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -452,8 +474,10 @@ static enum fx_status stream_read_all_bytes(
|
||||
}
|
||||
|
||||
static enum fx_status stream_read_all_bytes_s(
|
||||
struct stream_data *src, struct stream_data *dest,
|
||||
struct fx_stream_buffer_p *buffer, size_t *out_nr_read)
|
||||
struct stream_data *src,
|
||||
struct stream_data *dest,
|
||||
struct fx_stream_buffer_p *buffer,
|
||||
size_t *out_nr_read)
|
||||
{
|
||||
if (!(src->s_cfg->s_mode & FX_STREAM_READ)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -482,7 +506,10 @@ static enum fx_status stream_read_all_bytes_s(
|
||||
while (1) {
|
||||
size_t r = 0, w = 0;
|
||||
status = stream_read_bytes(
|
||||
src, buffer->p_buf, buffer->p_buf_len, &r);
|
||||
src,
|
||||
buffer->p_buf,
|
||||
buffer->p_buf_len,
|
||||
&r);
|
||||
if (status != FX_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
@@ -507,8 +534,10 @@ static enum fx_status stream_read_all_bytes_s(
|
||||
}
|
||||
|
||||
static enum fx_status stream_read_all_bytes_to_bstr_s(
|
||||
struct stream_data *src, struct fx_bstr *dest,
|
||||
struct fx_stream_buffer_p *buffer, size_t *out_nr_read)
|
||||
struct stream_data *src,
|
||||
struct fx_bstr *dest,
|
||||
struct fx_stream_buffer_p *buffer,
|
||||
size_t *out_nr_read)
|
||||
{
|
||||
if (!(src->s_cfg->s_mode & FX_STREAM_READ)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -533,7 +562,10 @@ static enum fx_status stream_read_all_bytes_to_bstr_s(
|
||||
while (1) {
|
||||
size_t r = 0, w = 0;
|
||||
status = stream_read_bytes(
|
||||
src, buffer->p_buf, buffer->p_buf_len, &r);
|
||||
src,
|
||||
buffer->p_buf,
|
||||
buffer->p_buf_len,
|
||||
&r);
|
||||
if (status != FX_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
@@ -557,8 +589,10 @@ static enum fx_status stream_read_all_bytes_to_bstr_s(
|
||||
return status;
|
||||
}
|
||||
|
||||
static enum fx_status stream_write_string(
|
||||
struct stream_data *stream, const char *s, size_t *nr_written)
|
||||
static enum fx_status stream_write_cstr(
|
||||
struct stream_data *stream,
|
||||
const char *s,
|
||||
size_t *nr_written)
|
||||
{
|
||||
size_t i;
|
||||
enum fx_status status = FX_SUCCESS;
|
||||
@@ -610,7 +644,8 @@ static enum fx_status stream_push_indent(struct stream_data *stream, int indent)
|
||||
stream->s_private->s_istack_ptr = 0;
|
||||
}
|
||||
|
||||
if (stream->s_private->s_istack_ptr + 1 >= stream->s_private->s_istack_size) {
|
||||
if (stream->s_private->s_istack_ptr + 1
|
||||
>= stream->s_private->s_istack_size) {
|
||||
int *buf = realloc(
|
||||
stream->s_private->s_istack,
|
||||
(stream->s_private->s_istack_size + 4) * sizeof(int));
|
||||
@@ -735,20 +770,31 @@ enum fx_status fx_stream_reserve(fx_stream *stream, size_t len)
|
||||
}
|
||||
|
||||
FX_CLASS_DISPATCH_VIRTUAL(
|
||||
fx_stream, FX_TYPE_STREAM, FX_ERR_NOT_SUPPORTED, s_reserve, stream,
|
||||
fx_stream,
|
||||
FX_TYPE_STREAM,
|
||||
FX_ERR_NOT_SUPPORTED,
|
||||
s_reserve,
|
||||
stream,
|
||||
len);
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_seek(
|
||||
fx_stream *stream, long long offset, fx_stream_seek_origin origin)
|
||||
fx_stream *stream,
|
||||
long long offset,
|
||||
fx_stream_seek_origin origin)
|
||||
{
|
||||
if (IS_BSTR(stream)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
FX_CLASS_DISPATCH_VIRTUAL(
|
||||
fx_stream, FX_TYPE_STREAM, FX_ERR_NOT_SUPPORTED, s_seek, stream,
|
||||
offset, origin);
|
||||
fx_stream,
|
||||
FX_TYPE_STREAM,
|
||||
FX_ERR_NOT_SUPPORTED,
|
||||
s_seek,
|
||||
stream,
|
||||
offset,
|
||||
origin);
|
||||
}
|
||||
|
||||
size_t fx_stream_cursor(const fx_stream *stream)
|
||||
@@ -788,7 +834,10 @@ enum fx_status fx_stream_read_char(fx_stream *strp, int *c)
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_read_bytes(
|
||||
fx_stream *strp, void *buf, size_t count, size_t *nr_read)
|
||||
fx_stream *strp,
|
||||
void *buf,
|
||||
size_t count,
|
||||
size_t *nr_read)
|
||||
{
|
||||
if (IS_BSTR(strp)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -833,17 +882,28 @@ enum fx_status fx_stream_read_line_s(fx_stream *src, fx_stream *dest)
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_read_all_bytes(
|
||||
fx_stream *stream, void *p, size_t max, size_t *out_nr_read)
|
||||
fx_stream *stream,
|
||||
void *p,
|
||||
size_t max,
|
||||
size_t *out_nr_read)
|
||||
{
|
||||
if (IS_BSTR(stream)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
STREAM_DISPATCH_VIRTUAL(stream_read_all_bytes, stream, p, max, out_nr_read);
|
||||
STREAM_DISPATCH_VIRTUAL(
|
||||
stream_read_all_bytes,
|
||||
stream,
|
||||
p,
|
||||
max,
|
||||
out_nr_read);
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_read_all_bytes_s(
|
||||
fx_stream *src, fx_stream *dest, fx_stream_buffer *buffer, size_t *out_nr_read)
|
||||
fx_stream *src,
|
||||
fx_stream *dest,
|
||||
fx_stream_buffer *buffer,
|
||||
size_t *out_nr_read)
|
||||
{
|
||||
if (IS_BSTR(src)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
@@ -865,7 +925,10 @@ enum fx_status fx_stream_read_all_bytes_s(
|
||||
|
||||
if (IS_BSTR(dest)) {
|
||||
return stream_read_all_bytes_to_bstr_s(
|
||||
&src_p, (fx_bstr *)dest, buffer_p, out_nr_read);
|
||||
&src_p,
|
||||
(fx_bstr *)dest,
|
||||
buffer_p,
|
||||
out_nr_read);
|
||||
}
|
||||
|
||||
status = stream_get_data(dest, &dest_p);
|
||||
@@ -885,34 +948,54 @@ enum fx_status fx_stream_write_char(fx_stream *stream, fx_wchar c)
|
||||
STREAM_DISPATCH_VIRTUAL(stream_write_char, stream, c);
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_write_string(
|
||||
fx_stream *stream, const char *s, size_t *nr_written)
|
||||
enum fx_status fx_stream_write_cstr(
|
||||
fx_stream *stream,
|
||||
const char *s,
|
||||
size_t *nr_written)
|
||||
{
|
||||
if (IS_BSTR(stream)) {
|
||||
return fx_bstr_write_cstr((fx_bstr *)stream, s, nr_written);
|
||||
}
|
||||
|
||||
STREAM_DISPATCH_VIRTUAL(stream_write_string, stream, s, nr_written);
|
||||
STREAM_DISPATCH_VIRTUAL(stream_write_cstr, stream, s, nr_written);
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_write_bytes(
|
||||
fx_stream *stream, const void *buf, size_t count, size_t *nr_written)
|
||||
fx_stream *stream,
|
||||
const void *buf,
|
||||
size_t count,
|
||||
size_t *nr_written)
|
||||
{
|
||||
if (IS_BSTR(stream)) {
|
||||
return fx_bstr_write_chars((fx_bstr *)stream, buf, count, nr_written);
|
||||
return fx_bstr_write_chars(
|
||||
(fx_bstr *)stream,
|
||||
buf,
|
||||
count,
|
||||
nr_written);
|
||||
}
|
||||
|
||||
STREAM_DISPATCH_VIRTUAL(stream_write_bytes, stream, buf, count, nr_written);
|
||||
STREAM_DISPATCH_VIRTUAL(
|
||||
stream_write_bytes,
|
||||
stream,
|
||||
buf,
|
||||
count,
|
||||
nr_written);
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_write_fmt(
|
||||
fx_stream *stream, size_t *nr_written, const char *format, ...)
|
||||
fx_stream *stream,
|
||||
size_t *nr_written,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
if (IS_BSTR(stream)) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
fx_status w = fx_bstr_write_vfmt(
|
||||
(fx_bstr *)stream, nr_written, format, arg);
|
||||
(fx_bstr *)stream,
|
||||
nr_written,
|
||||
format,
|
||||
arg);
|
||||
va_end(arg);
|
||||
|
||||
return w;
|
||||
@@ -934,10 +1017,17 @@ enum fx_status fx_stream_write_fmt(
|
||||
}
|
||||
|
||||
enum fx_status fx_stream_write_vfmt(
|
||||
fx_stream *stream, size_t *nr_written, const char *format, va_list arg)
|
||||
fx_stream *stream,
|
||||
size_t *nr_written,
|
||||
const char *format,
|
||||
va_list arg)
|
||||
{
|
||||
if (IS_BSTR(stream)) {
|
||||
return fx_bstr_write_vfmt((fx_bstr *)stream, nr_written, format, arg);
|
||||
return fx_bstr_write_vfmt(
|
||||
(fx_bstr *)stream,
|
||||
nr_written,
|
||||
format,
|
||||
arg);
|
||||
}
|
||||
|
||||
struct stream_data p;
|
||||
@@ -997,7 +1087,10 @@ static void stdio_stream_fini(fx_object *obj, void *priv)
|
||||
}
|
||||
|
||||
static enum fx_status stdio_read(
|
||||
fx_stream *stream, void *out, size_t max, size_t *nr_read)
|
||||
fx_stream *stream,
|
||||
void *out,
|
||||
size_t max,
|
||||
size_t *nr_read)
|
||||
{
|
||||
struct fx_stdio_stream_p *p
|
||||
= fx_object_get_private(stream, FX_TYPE_STDIO_STREAM);
|
||||
@@ -1015,7 +1108,10 @@ static enum fx_status stdio_read(
|
||||
}
|
||||
|
||||
static enum fx_status stdio_write(
|
||||
fx_stream *stream, const void *data, size_t count, size_t *nr_written)
|
||||
fx_stream *stream,
|
||||
const void *data,
|
||||
size_t count,
|
||||
size_t *nr_written)
|
||||
{
|
||||
struct fx_stdio_stream_p *p
|
||||
= fx_object_get_private(stream, FX_TYPE_STDIO_STREAM);
|
||||
@@ -1032,7 +1128,9 @@ static enum fx_status stdio_write(
|
||||
}
|
||||
|
||||
static enum fx_status stdio_seek(
|
||||
fx_stream *stream, long long offset, fx_stream_seek_origin origin)
|
||||
fx_stream *stream,
|
||||
long long offset,
|
||||
fx_stream_seek_origin origin)
|
||||
{
|
||||
struct fx_stdio_stream_p *p
|
||||
= fx_object_get_private(stream, FX_TYPE_STDIO_STREAM);
|
||||
|
||||
+14
-7
@@ -31,7 +31,8 @@ static fx_status resize_array(struct fx_array_p *array, size_t new_capacity)
|
||||
{
|
||||
if (array->ar_cap < new_capacity) {
|
||||
void *new_data = realloc(
|
||||
array->ar_data, new_capacity * sizeof(struct fx_dsref *));
|
||||
array->ar_data,
|
||||
new_capacity * sizeof(struct fx_dsref *));
|
||||
if (!new_data) {
|
||||
return FX_ERR_NO_MEMORY;
|
||||
}
|
||||
@@ -43,7 +44,8 @@ static fx_status resize_array(struct fx_array_p *array, size_t new_capacity)
|
||||
}
|
||||
|
||||
void *new_data = realloc(
|
||||
array->ar_data, new_capacity * sizeof(struct fx_dsref *));
|
||||
array->ar_data,
|
||||
new_capacity * sizeof(struct fx_dsref *));
|
||||
if (!new_data) {
|
||||
return FX_ERR_NO_MEMORY;
|
||||
}
|
||||
@@ -59,7 +61,10 @@ static fx_status resize_array(struct fx_array_p *array, size_t new_capacity)
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_status array_insert(struct fx_array_p *array, fx_object *value, size_t at)
|
||||
static fx_status array_insert(
|
||||
struct fx_array_p *array,
|
||||
fx_object *value,
|
||||
size_t at)
|
||||
{
|
||||
if (at == FX_NPOS) {
|
||||
at = array->ar_len;
|
||||
@@ -193,7 +198,9 @@ static void array_clear(struct fx_array_p *array)
|
||||
|
||||
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
fx_array *fx_array_create_with_values(fx_object *const *values, size_t nr_values)
|
||||
fx_array *fx_array_create_with_values(
|
||||
fx_object *const *values,
|
||||
size_t nr_values)
|
||||
{
|
||||
fx_array *array = fx_array_create();
|
||||
if (!array) {
|
||||
@@ -323,11 +330,11 @@ static void array_to_string(const fx_object *obj, fx_stream *out)
|
||||
struct fx_array_p *array = fx_object_get_private(obj, FX_TYPE_ARRAY);
|
||||
|
||||
if (!array->ar_len) {
|
||||
fx_stream_write_string(out, "[]", NULL);
|
||||
fx_stream_write_cstr(out, "[]", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
fx_stream_write_string(out, "[\n", NULL);
|
||||
fx_stream_write_cstr(out, "[\n", NULL);
|
||||
|
||||
fx_stream_push_indent(out, 1);
|
||||
size_t len = array_size(array);
|
||||
@@ -347,7 +354,7 @@ static void array_to_string(const fx_object *obj, fx_stream *out)
|
||||
}
|
||||
|
||||
if (i < len - 1) {
|
||||
fx_stream_write_string(out, ",", NULL);
|
||||
fx_stream_write_cstr(out, ",", NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_char(out, '\n');
|
||||
|
||||
@@ -36,9 +36,16 @@ struct fx_dict_iterator_p {
|
||||
/*** MISC FUNCTIONS ***********************************************************/
|
||||
|
||||
static FX_BST_DEFINE_SIMPLE_GET(
|
||||
struct fx_dict_bucket, uint64_t, bk_node, bk_hash, get_bucket);
|
||||
struct fx_dict_bucket,
|
||||
uint64_t,
|
||||
bk_node,
|
||||
bk_hash,
|
||||
get_bucket);
|
||||
static FX_BST_DEFINE_SIMPLE_INSERT(
|
||||
struct fx_dict_bucket, bk_node, bk_hash, put_bucket);
|
||||
struct fx_dict_bucket,
|
||||
bk_node,
|
||||
bk_hash,
|
||||
put_bucket);
|
||||
|
||||
uint64_t fx_cstr_hash(const char *s)
|
||||
{
|
||||
@@ -79,7 +86,10 @@ static struct fx_dict_bucket_item *create_bucket_item(void)
|
||||
return item;
|
||||
}
|
||||
|
||||
static fx_status dict_put(struct fx_dict_p *dict, const char *key, fx_object *value)
|
||||
static fx_status dict_put(
|
||||
struct fx_dict_p *dict,
|
||||
const char *key,
|
||||
fx_object *value)
|
||||
{
|
||||
uint64_t hash = fx_cstr_hash(key);
|
||||
struct fx_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
||||
@@ -107,7 +117,9 @@ static fx_status dict_put(struct fx_dict_p *dict, const char *key, fx_object *va
|
||||
}
|
||||
|
||||
static fx_status dict_put_sk(
|
||||
struct fx_dict_p *dict, const fx_string *key, fx_object *value)
|
||||
struct fx_dict_p *dict,
|
||||
const fx_string *key,
|
||||
fx_object *value)
|
||||
{
|
||||
uint64_t hash = fx_string_hash(key);
|
||||
struct fx_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
||||
@@ -147,7 +159,7 @@ static fx_object *dict_at(const struct fx_dict_p *dict, const char *key)
|
||||
struct fx_dict_bucket_item *item
|
||||
= fx_unbox(struct fx_dict_bucket_item, entry, bi_entry);
|
||||
|
||||
if (!strcmp(fx_string_ptr(item->bi_str), key)) {
|
||||
if (!strcmp(fx_string_get_cstr(item->bi_str), key)) {
|
||||
return item->bi_value;
|
||||
}
|
||||
|
||||
@@ -250,8 +262,10 @@ static bool dict_is_empty(const struct fx_dict_p *dict)
|
||||
}
|
||||
|
||||
static bool get_next_node(
|
||||
struct fx_bst_node *cur_node, struct fx_queue_entry *cur_entry,
|
||||
struct fx_bst_node **out_next_node, struct fx_queue_entry **out_next_entry)
|
||||
struct fx_bst_node *cur_node,
|
||||
struct fx_queue_entry *cur_entry,
|
||||
struct fx_bst_node **out_next_node,
|
||||
struct fx_queue_entry **out_next_entry)
|
||||
{
|
||||
struct fx_dict_bucket *cur_bucket
|
||||
= fx_unbox(struct fx_dict_bucket, cur_node, bk_node);
|
||||
@@ -298,7 +312,8 @@ static bool get_next_node(
|
||||
}
|
||||
|
||||
static fx_status delete_item(
|
||||
struct fx_dict_p *dict, struct fx_dict_bucket *bucket,
|
||||
struct fx_dict_p *dict,
|
||||
struct fx_dict_bucket *bucket,
|
||||
struct fx_dict_bucket_item *item)
|
||||
{
|
||||
fx_queue_delete(&bucket->bk_items, &item->bi_entry);
|
||||
@@ -401,11 +416,15 @@ static void dict_fini(fx_object *obj, void *priv)
|
||||
struct fx_bst_node *next_node = fx_bst_next(node);
|
||||
fx_bst_delete(&dict->d_buckets, node);
|
||||
|
||||
struct fx_queue_entry *entry = fx_queue_first(&bucket->bk_items);
|
||||
struct fx_queue_entry *entry
|
||||
= fx_queue_first(&bucket->bk_items);
|
||||
while (entry) {
|
||||
struct fx_dict_bucket_item *item = fx_unbox(
|
||||
struct fx_dict_bucket_item, entry, bi_entry);
|
||||
struct fx_queue_entry *next_entry = fx_queue_next(entry);
|
||||
struct fx_dict_bucket_item,
|
||||
entry,
|
||||
bi_entry);
|
||||
struct fx_queue_entry *next_entry
|
||||
= fx_queue_next(entry);
|
||||
fx_queue_delete(&bucket->bk_items, entry);
|
||||
|
||||
free(item->bi_str);
|
||||
@@ -425,11 +444,11 @@ static void dict_to_string(const fx_object *obj, fx_stream *out)
|
||||
struct fx_dict_p *dict = fx_object_get_private(obj, FX_TYPE_DICT);
|
||||
|
||||
if (dict_is_empty(dict)) {
|
||||
fx_stream_write_string(out, "{}", NULL);
|
||||
fx_stream_write_cstr(out, "{}", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
fx_stream_write_string(out, "{\n", NULL);
|
||||
fx_stream_write_cstr(out, "{\n", NULL);
|
||||
|
||||
fx_stream_push_indent(out, 1);
|
||||
size_t len = dict_get_size(dict);
|
||||
@@ -440,16 +459,20 @@ static void dict_to_string(const fx_object *obj, fx_stream *out)
|
||||
struct fx_dict_bucket *bucket
|
||||
= fx_unbox(struct fx_dict_bucket, node, bk_node);
|
||||
|
||||
struct fx_queue_entry *entry = fx_queue_first(&bucket->bk_items);
|
||||
struct fx_queue_entry *entry
|
||||
= fx_queue_first(&bucket->bk_items);
|
||||
while (entry) {
|
||||
struct fx_dict_bucket_item *item = fx_unbox(
|
||||
struct fx_dict_bucket_item, entry, bi_entry);
|
||||
struct fx_dict_bucket_item,
|
||||
entry,
|
||||
bi_entry);
|
||||
|
||||
fx_object_to_string(item->bi_str, out);
|
||||
fx_stream_write_string(out, ": ", NULL);
|
||||
fx_stream_write_cstr(out, ": ", NULL);
|
||||
|
||||
bool is_string = fx_object_is_type(
|
||||
item->bi_value, FX_TYPE_STRING);
|
||||
item->bi_value,
|
||||
FX_TYPE_STRING);
|
||||
|
||||
if (is_string) {
|
||||
fx_stream_write_char(out, '"');
|
||||
@@ -462,7 +485,7 @@ static void dict_to_string(const fx_object *obj, fx_stream *out)
|
||||
}
|
||||
|
||||
if (i < len - 1) {
|
||||
fx_stream_write_string(out, ",", NULL);
|
||||
fx_stream_write_cstr(out, ",", NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_char(out, '\n');
|
||||
|
||||
+38
-23
@@ -1,12 +1,12 @@
|
||||
#ifndef FX_DS_STRING_H_
|
||||
#define FX_DS_STRING_H_
|
||||
|
||||
#include <ctype.h>
|
||||
#include <fx/core/encoding.h>
|
||||
#include <fx/core/iterator.h>
|
||||
#include <fx/core/macros.h>
|
||||
#include <fx/core/status.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <ctype.h>
|
||||
|
||||
FX_DECLS_BEGIN;
|
||||
|
||||
@@ -52,18 +52,22 @@ FX_API fx_string *fx_string_duplicate(const fx_string *str);
|
||||
FX_API char *fx_string_steal(fx_string *str);
|
||||
FX_API fx_status fx_string_reserve(fx_string *str, size_t capacity);
|
||||
FX_API fx_status fx_string_replace(
|
||||
fx_string *str, size_t start, size_t length, const char *new_data);
|
||||
fx_string *str,
|
||||
size_t start,
|
||||
size_t length,
|
||||
const char *new_data);
|
||||
FX_API fx_status fx_string_replace_all(fx_string *str, const char *new_data);
|
||||
FX_API fx_status fx_string_replace_all_with_stringstream(
|
||||
fx_string *str, const fx_stringstream *new_data);
|
||||
fx_string *str,
|
||||
const fx_stringstream *new_data);
|
||||
FX_API fx_status fx_string_remove(fx_string *str, size_t start, size_t length);
|
||||
FX_API fx_status fx_string_transform(fx_string *str, int (*transformer)(int));
|
||||
FX_API fx_status fx_string_trim(fx_string *str);
|
||||
static inline fx_status fx_string_toupper(fx_string *str)
|
||||
static inline fx_status fx_string_transform_uppercase(fx_string *str)
|
||||
{
|
||||
return fx_string_transform(str, toupper);
|
||||
}
|
||||
static inline fx_status fx_string_tolower(fx_string *str)
|
||||
static inline fx_status fx_string_transform_lowercase(fx_string *str)
|
||||
{
|
||||
return fx_string_transform(str, tolower);
|
||||
}
|
||||
@@ -73,30 +77,36 @@ FX_API fx_status fx_string_append_wc(fx_string *dest, fx_wchar c);
|
||||
FX_API fx_status fx_string_append_s(fx_string *dest, const fx_string *src);
|
||||
FX_API fx_status fx_string_append_cstr(fx_string *dest, const char *src);
|
||||
FX_API fx_status fx_string_append_wstr(fx_string *dest, const fx_wchar *src);
|
||||
FX_API fx_status fx_string_append_cstrf(fx_string *dest, const char *format, ...);
|
||||
FX_API fx_status
|
||||
fx_string_append_cstrf(fx_string *dest, const char *format, ...);
|
||||
|
||||
FX_API fx_status fx_string_prepend_c(fx_string *dest, char c);
|
||||
FX_API fx_status fx_string_prepend_wc(fx_string *dest, fx_wchar c);
|
||||
FX_API fx_status fx_string_prepend_cstr(fx_string *dest, const char *src);
|
||||
FX_API fx_status fx_string_prepend_wstr(fx_string *dest, const fx_wchar *src);
|
||||
FX_API fx_status fx_string_prepend_cstrf(fx_string *dest, const char *format, ...);
|
||||
FX_API fx_status
|
||||
fx_string_prepend_cstrf(fx_string *dest, const char *format, ...);
|
||||
|
||||
FX_API fx_status fx_string_insert_c(fx_string *dest, char c, size_t at);
|
||||
FX_API fx_status fx_string_insert_wc(fx_string *dest, fx_wchar c, size_t at);
|
||||
FX_API fx_status fx_string_insert_s(fx_string *dest, const fx_string *src, size_t at);
|
||||
FX_API fx_status fx_string_insert_cstr(fx_string *dest, const char *src, size_t at);
|
||||
FX_API fx_status fx_string_insert_wstr(
|
||||
fx_string *dest, const fx_wchar *src, size_t at);
|
||||
FX_API fx_status fx_string_insert_cstrn(
|
||||
fx_string *dest, const char *src, size_t len, size_t at);
|
||||
FX_API fx_status fx_string_insert_wstrn(
|
||||
fx_string *dest, const char *src, size_t len, size_t at);
|
||||
FX_API fx_status fx_string_insert_cstrf(
|
||||
fx_string *dest, size_t at, const char *format, ...);
|
||||
FX_API fx_status
|
||||
fx_string_insert_s(fx_string *dest, const fx_string *src, size_t at);
|
||||
FX_API fx_status
|
||||
fx_string_insert_cstr(fx_string *dest, const char *src, size_t at);
|
||||
FX_API fx_status
|
||||
fx_string_insert_wstr(fx_string *dest, const fx_wchar *src, size_t at);
|
||||
FX_API fx_status
|
||||
fx_string_insert_cstrn(fx_string *dest, const char *src, size_t len, size_t at);
|
||||
FX_API fx_status
|
||||
fx_string_insert_wstrn(fx_string *dest, const char *src, size_t len, size_t at);
|
||||
FX_API fx_status
|
||||
fx_string_insert_cstrf(fx_string *dest, size_t at, const char *format, ...);
|
||||
FX_API void fx_string_clear(fx_string *str);
|
||||
|
||||
FX_API fx_iterator *fx_string_tokenise(
|
||||
fx_string *str, const char *delims[], size_t nr_delims,
|
||||
fx_string *str,
|
||||
const char *delims[],
|
||||
size_t nr_delims,
|
||||
fx_string_tokenise_flags flags);
|
||||
|
||||
FX_API size_t fx_string_get_size(const fx_string *str, fx_strlen_flags flags);
|
||||
@@ -104,15 +114,20 @@ FX_API size_t fx_string_get_capacity(const fx_string *str);
|
||||
|
||||
FX_API bool fx_string_compare(const fx_string *a, const fx_string *b);
|
||||
|
||||
FX_API char fx_string_front(const fx_string *str);
|
||||
FX_API char fx_string_back(const fx_string *str);
|
||||
FX_API char fx_string_get_first_char(const fx_string *str);
|
||||
FX_API char fx_string_get_last_char(const fx_string *str);
|
||||
|
||||
FX_API void fx_string_pop_back(fx_string *str);
|
||||
|
||||
FX_API const char *fx_string_ptr(const fx_string *str);
|
||||
FX_API fx_string *fx_string_substr(const fx_string *str, size_t start, size_t len);
|
||||
FX_API const char *fx_string_get_cstr(const fx_string *str);
|
||||
FX_API fx_string *fx_string_get_substr(
|
||||
const fx_string *str,
|
||||
size_t start,
|
||||
size_t len);
|
||||
|
||||
FX_API int fx_string_iterator_begin(const fx_string *string, fx_string_iterator *it);
|
||||
FX_API int fx_string_iterator_begin(
|
||||
const fx_string *string,
|
||||
fx_string_iterator *it);
|
||||
FX_API bool fx_string_iterator_next(fx_string_iterator *it);
|
||||
// FX_API fx_status fx_string_iterator_erase(fx_string_iterator *it);
|
||||
FX_API bool fx_string_iterator_is_valid(const fx_string_iterator *it);
|
||||
|
||||
+244
-71
@@ -34,7 +34,8 @@ struct fx_number_p {
|
||||
|
||||
typedef int (*number_converter_t)(const struct fx_number_p *, void *);
|
||||
|
||||
static number_converter_t converters[FX_NUMBER_TYPE_COUNT][FX_NUMBER_TYPE_COUNT];
|
||||
static number_converter_t converters[FX_NUMBER_TYPE_COUNT]
|
||||
[FX_NUMBER_TYPE_COUNT];
|
||||
|
||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||
|
||||
@@ -44,7 +45,9 @@ static fx_number_type number_get_number_type(const struct fx_number_p *number)
|
||||
}
|
||||
|
||||
static int number_get_value(
|
||||
const struct fx_number_p *number, fx_number_type type, void *value_ptr)
|
||||
const struct fx_number_p *number,
|
||||
fx_number_type type,
|
||||
void *value_ptr)
|
||||
{
|
||||
fx_number_type srb_type = number->n_type;
|
||||
fx_number_type dest_type = type;
|
||||
@@ -532,110 +535,188 @@ static void print_inf(const struct fx_number_p *n, fx_stream *out)
|
||||
{
|
||||
switch (n->n_type) {
|
||||
case FX_NUMBER_INT8:
|
||||
fx_stream_write_string(out, n->n_value.v_int8 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int8 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT16:
|
||||
fx_stream_write_string(out, n->n_value.v_int16 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int16 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT32:
|
||||
fx_stream_write_string(out, n->n_value.v_int32 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int32 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT64:
|
||||
fx_stream_write_string(out, n->n_value.v_int64 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int64 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT32:
|
||||
fx_stream_write_string(
|
||||
out, n->n_value.v_float32 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_float32 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT64:
|
||||
fx_stream_write_string(
|
||||
out, n->n_value.v_float64 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_float64 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_CHAR:
|
||||
fx_stream_write_string(out, n->n_value.v_char < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_char < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_SHORT:
|
||||
fx_stream_write_string(out, n->n_value.v_short < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_short < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT:
|
||||
fx_stream_write_string(out, n->n_value.v_int < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_LONG:
|
||||
fx_stream_write_string(out, n->n_value.v_long < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_long < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_LONGLONG:
|
||||
fx_stream_write_string(
|
||||
out, n->n_value.v_longlong < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_longlong < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT:
|
||||
fx_stream_write_string(out, n->n_value.v_float < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_float < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_DOUBLE:
|
||||
fx_stream_write_string(out, n->n_value.v_double < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_double < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_SIZE_T:
|
||||
fx_stream_write_string(out, n->n_value.v_size_t < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_size_t < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fx_stream_write_string(out, "INF", NULL);
|
||||
fx_stream_write_cstr(out, "INF", NULL);
|
||||
}
|
||||
|
||||
static void print_nan(const struct fx_number_p *n, fx_stream *out)
|
||||
{
|
||||
switch (n->n_type) {
|
||||
case FX_NUMBER_INT8:
|
||||
fx_stream_write_string(out, n->n_value.v_int8 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int8 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT16:
|
||||
fx_stream_write_string(out, n->n_value.v_int16 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int16 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT32:
|
||||
fx_stream_write_string(out, n->n_value.v_int32 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int32 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT64:
|
||||
fx_stream_write_string(out, n->n_value.v_int64 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int64 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT32:
|
||||
fx_stream_write_string(
|
||||
out, n->n_value.v_float32 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_float32 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT64:
|
||||
fx_stream_write_string(
|
||||
out, n->n_value.v_float64 < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_float64 < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_CHAR:
|
||||
fx_stream_write_string(out, n->n_value.v_char < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_char < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_SHORT:
|
||||
fx_stream_write_string(out, n->n_value.v_short < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_short < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_INT:
|
||||
fx_stream_write_string(out, n->n_value.v_int < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_int < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_LONG:
|
||||
fx_stream_write_string(out, n->n_value.v_long < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_long < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_LONGLONG:
|
||||
fx_stream_write_string(
|
||||
out, n->n_value.v_longlong < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_longlong < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT:
|
||||
fx_stream_write_string(out, n->n_value.v_float < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_float < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_DOUBLE:
|
||||
fx_stream_write_string(out, n->n_value.v_double < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_double < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
case FX_NUMBER_SIZE_T:
|
||||
fx_stream_write_string(out, n->n_value.v_size_t < 0 ? "-" : "", NULL);
|
||||
fx_stream_write_cstr(
|
||||
out,
|
||||
n->n_value.v_size_t < 0 ? "-" : "",
|
||||
NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fx_stream_write_string(out, "NaN", NULL);
|
||||
fx_stream_write_cstr(out, "NaN", NULL);
|
||||
}
|
||||
|
||||
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||
@@ -660,27 +741,37 @@ fx_number *fx_number_create(fx_number_type type, void *value_ptr)
|
||||
memcpy(&p->n_value.v_int8, value_ptr, sizeof p->n_value.v_int8);
|
||||
break;
|
||||
case FX_NUMBER_INT16:
|
||||
memcpy(&p->n_value.v_int16, value_ptr, sizeof p->n_value.v_int16);
|
||||
memcpy(&p->n_value.v_int16,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_int16);
|
||||
break;
|
||||
case FX_NUMBER_INT32:
|
||||
memcpy(&p->n_value.v_int32, value_ptr, sizeof p->n_value.v_int32);
|
||||
memcpy(&p->n_value.v_int32,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_int32);
|
||||
break;
|
||||
case FX_NUMBER_INT64:
|
||||
memcpy(&p->n_value.v_int64, value_ptr, sizeof p->n_value.v_int64);
|
||||
memcpy(&p->n_value.v_int64,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_int64);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT32:
|
||||
memcpy(&p->n_value.v_float32, value_ptr,
|
||||
memcpy(&p->n_value.v_float32,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_float32);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT64:
|
||||
memcpy(&p->n_value.v_float64, value_ptr,
|
||||
memcpy(&p->n_value.v_float64,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_float64);
|
||||
break;
|
||||
case FX_NUMBER_CHAR:
|
||||
memcpy(&p->n_value.v_char, value_ptr, sizeof p->n_value.v_char);
|
||||
break;
|
||||
case FX_NUMBER_SHORT:
|
||||
memcpy(&p->n_value.v_short, value_ptr, sizeof p->n_value.v_short);
|
||||
memcpy(&p->n_value.v_short,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_short);
|
||||
break;
|
||||
case FX_NUMBER_INT:
|
||||
memcpy(&p->n_value.v_int, value_ptr, sizeof p->n_value.v_int);
|
||||
@@ -689,17 +780,24 @@ fx_number *fx_number_create(fx_number_type type, void *value_ptr)
|
||||
memcpy(&p->n_value.v_long, value_ptr, sizeof p->n_value.v_long);
|
||||
break;
|
||||
case FX_NUMBER_LONGLONG:
|
||||
memcpy(&p->n_value.v_longlong, value_ptr,
|
||||
memcpy(&p->n_value.v_longlong,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_longlong);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT:
|
||||
memcpy(&p->n_value.v_float, value_ptr, sizeof p->n_value.v_float);
|
||||
memcpy(&p->n_value.v_float,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_float);
|
||||
break;
|
||||
case FX_NUMBER_DOUBLE:
|
||||
memcpy(&p->n_value.v_double, value_ptr, sizeof p->n_value.v_double);
|
||||
memcpy(&p->n_value.v_double,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_double);
|
||||
break;
|
||||
case FX_NUMBER_SIZE_T:
|
||||
memcpy(&p->n_value.v_size_t, value_ptr, sizeof p->n_value.v_size_t);
|
||||
memcpy(&p->n_value.v_size_t,
|
||||
value_ptr,
|
||||
sizeof p->n_value.v_size_t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -710,13 +808,23 @@ fx_number *fx_number_create(fx_number_type type, void *value_ptr)
|
||||
|
||||
fx_number_type fx_number_get_number_type(const fx_number *number)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_NUMBER, number_get_number_type, number);
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
FX_TYPE_NUMBER,
|
||||
number_get_number_type,
|
||||
number);
|
||||
}
|
||||
|
||||
int fx_number_get_value(const fx_number *number, fx_number_type type, void *value_ptr)
|
||||
int fx_number_get_value(
|
||||
const fx_number *number,
|
||||
fx_number_type type,
|
||||
void *value_ptr)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_NUMBER, number_get_value, number, type, value_ptr);
|
||||
FX_TYPE_NUMBER,
|
||||
number_get_value,
|
||||
number,
|
||||
type,
|
||||
value_ptr);
|
||||
}
|
||||
|
||||
bool fx_number_is_integer(const fx_number *number)
|
||||
@@ -736,12 +844,18 @@ bool fx_number_is_inf(const fx_number *number)
|
||||
|
||||
bool fx_number_is_inf_positive(const fx_number *number)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_NUMBER, number_is_inf_positive, number);
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
FX_TYPE_NUMBER,
|
||||
number_is_inf_positive,
|
||||
number);
|
||||
}
|
||||
|
||||
bool fx_number_is_inf_negative(const fx_number *number)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_NUMBER, number_is_inf_negative, number);
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
FX_TYPE_NUMBER,
|
||||
number_is_inf_negative,
|
||||
number);
|
||||
}
|
||||
|
||||
bool fx_number_is_nan(const fx_number *number)
|
||||
@@ -751,32 +865,54 @@ bool fx_number_is_nan(const fx_number *number)
|
||||
|
||||
bool fx_number_is_nan_positive(const fx_number *number)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_NUMBER, number_is_nan_positive, number);
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
FX_TYPE_NUMBER,
|
||||
number_is_nan_positive,
|
||||
number);
|
||||
}
|
||||
|
||||
bool fx_number_is_nan_negative(const fx_number *number)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_NUMBER, number_is_nan_negative, number);
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
FX_TYPE_NUMBER,
|
||||
number_is_nan_negative,
|
||||
number);
|
||||
}
|
||||
|
||||
void fx_number_set_inf_positive(fx_number *number, bool v)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_NUMBER, number_set_inf_positive, number, v);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_NUMBER,
|
||||
number_set_inf_positive,
|
||||
number,
|
||||
v);
|
||||
}
|
||||
|
||||
void fx_number_set_inf_negative(fx_number *number, bool v)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_NUMBER, number_set_inf_negative, number, v);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_NUMBER,
|
||||
number_set_inf_negative,
|
||||
number,
|
||||
v);
|
||||
}
|
||||
|
||||
void fx_number_set_nan_positive(fx_number *number, bool v)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_NUMBER, number_set_nan_positive, number, v);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_NUMBER,
|
||||
number_set_nan_positive,
|
||||
number,
|
||||
v);
|
||||
}
|
||||
|
||||
void fx_number_set_nan_negative(fx_number *number, bool v)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_NUMBER, number_set_nan_negative, number, v);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_NUMBER,
|
||||
number_set_nan_negative,
|
||||
number,
|
||||
v);
|
||||
}
|
||||
|
||||
size_t fx_number_data_size(const fx_number *number)
|
||||
@@ -812,22 +948,42 @@ static void number_to_string(const fx_object *obj, fx_stream *out)
|
||||
|
||||
switch (number->n_type) {
|
||||
case FX_NUMBER_INT8:
|
||||
fx_stream_write_fmt(out, NULL, "%" PRIu8, number->n_value.v_int8);
|
||||
fx_stream_write_fmt(
|
||||
out,
|
||||
NULL,
|
||||
"%" PRIu8,
|
||||
number->n_value.v_int8);
|
||||
break;
|
||||
case FX_NUMBER_INT16:
|
||||
fx_stream_write_fmt(out, NULL, "%" PRIu16, number->n_value.v_int16);
|
||||
fx_stream_write_fmt(
|
||||
out,
|
||||
NULL,
|
||||
"%" PRIu16,
|
||||
number->n_value.v_int16);
|
||||
break;
|
||||
case FX_NUMBER_INT32:
|
||||
fx_stream_write_fmt(out, NULL, "%" PRIu32, number->n_value.v_int32);
|
||||
fx_stream_write_fmt(
|
||||
out,
|
||||
NULL,
|
||||
"%" PRIu32,
|
||||
number->n_value.v_int32);
|
||||
break;
|
||||
case FX_NUMBER_INT64:
|
||||
fx_stream_write_fmt(out, NULL, "%" PRIu64, number->n_value.v_int64);
|
||||
fx_stream_write_fmt(
|
||||
out,
|
||||
NULL,
|
||||
"%" PRIu64,
|
||||
number->n_value.v_int64);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT32:
|
||||
fx_stream_write_fmt(out, NULL, "%f", number->n_value.v_float32);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT64:
|
||||
fx_stream_write_fmt(out, NULL, "%lf", number->n_value.v_float64);
|
||||
fx_stream_write_fmt(
|
||||
out,
|
||||
NULL,
|
||||
"%lf",
|
||||
number->n_value.v_float64);
|
||||
break;
|
||||
case FX_NUMBER_CHAR:
|
||||
fx_stream_write_fmt(out, NULL, "%d", number->n_value.v_char);
|
||||
@@ -842,7 +998,11 @@ static void number_to_string(const fx_object *obj, fx_stream *out)
|
||||
fx_stream_write_fmt(out, NULL, "%ld", number->n_value.v_long);
|
||||
break;
|
||||
case FX_NUMBER_LONGLONG:
|
||||
fx_stream_write_fmt(out, NULL, "%lld", number->n_value.v_longlong);
|
||||
fx_stream_write_fmt(
|
||||
out,
|
||||
NULL,
|
||||
"%lld",
|
||||
number->n_value.v_longlong);
|
||||
break;
|
||||
case FX_NUMBER_FLOAT:
|
||||
fx_stream_write_fmt(out, NULL, "%f", number->n_value.v_float);
|
||||
@@ -855,7 +1015,10 @@ static void number_to_string(const fx_object *obj, fx_stream *out)
|
||||
break;
|
||||
case FX_NUMBER_HANDLE:
|
||||
fx_stream_write_fmt(
|
||||
out, NULL, "%016" PRIx64, number->n_value.v_size_t);
|
||||
out,
|
||||
NULL,
|
||||
"%016" PRIx64,
|
||||
number->n_value.v_size_t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1286,7 +1449,9 @@ static int float32_to_long(const struct fx_number_p *number, void *value_ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int float32_to_longlong(const struct fx_number_p *number, void *value_ptr)
|
||||
static int float32_to_longlong(
|
||||
const struct fx_number_p *number,
|
||||
void *value_ptr)
|
||||
{
|
||||
*(long long *)value_ptr = number->n_value.v_float32;
|
||||
return 0;
|
||||
@@ -1372,7 +1537,9 @@ static int float64_to_long(const struct fx_number_p *number, void *value_ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int float64_to_longlong(const struct fx_number_p *number, void *value_ptr)
|
||||
static int float64_to_longlong(
|
||||
const struct fx_number_p *number,
|
||||
void *value_ptr)
|
||||
{
|
||||
*(long long *)value_ptr = number->n_value.v_float64;
|
||||
return 0;
|
||||
@@ -1766,13 +1933,17 @@ static int longlong_to_int64(const struct fx_number_p *number, void *value_ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int longlong_to_float32(const struct fx_number_p *number, void *value_ptr)
|
||||
static int longlong_to_float32(
|
||||
const struct fx_number_p *number,
|
||||
void *value_ptr)
|
||||
{
|
||||
*(float *)value_ptr = number->n_value.v_longlong;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int longlong_to_float64(const struct fx_number_p *number, void *value_ptr)
|
||||
static int longlong_to_float64(
|
||||
const struct fx_number_p *number,
|
||||
void *value_ptr)
|
||||
{
|
||||
*(double *)value_ptr = number->n_value.v_longlong;
|
||||
return 0;
|
||||
@@ -1802,7 +1973,9 @@ static int longlong_to_long(const struct fx_number_p *number, void *value_ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int longlong_to_longlong(const struct fx_number_p *number, void *value_ptr)
|
||||
static int longlong_to_longlong(
|
||||
const struct fx_number_p *number,
|
||||
void *value_ptr)
|
||||
{
|
||||
*(long long *)value_ptr = number->n_value.v_longlong;
|
||||
return 0;
|
||||
|
||||
+217
-66
@@ -1,7 +1,7 @@
|
||||
#include <ctype.h>
|
||||
#include <fx/core/stream.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -27,7 +27,8 @@ enum iterator_mode {
|
||||
|
||||
struct fx_string_p {
|
||||
/* length of string in bytes, not including null-terminator.
|
||||
* a multi-byte utf-8 codepoint will be counted as multiple bytes here */
|
||||
* a multi-byte utf-8 codepoint will be counted as multiple bytes here
|
||||
*/
|
||||
unsigned int s_len;
|
||||
/* length of string in codepoints, not including null-terminator.
|
||||
* a multi-byte utf-8 codepoint will be counted as one codepoint here */
|
||||
@@ -76,8 +77,11 @@ static char *string_ptr(const struct fx_string_p *str)
|
||||
}
|
||||
|
||||
static enum fx_status convert_codepoint_range_to_byte_range(
|
||||
const struct fx_string_p *str, size_t cp_start, size_t cp_length,
|
||||
size_t *out_byte_start, size_t *out_byte_length)
|
||||
const struct fx_string_p *str,
|
||||
size_t cp_start,
|
||||
size_t cp_length,
|
||||
size_t *out_byte_start,
|
||||
size_t *out_byte_length)
|
||||
{
|
||||
const char *s = string_ptr(str);
|
||||
size_t byte_offset = 0, byte_length = 0;
|
||||
@@ -146,7 +150,9 @@ static char *get_next_codepoint(struct fx_string_p *str, char *this_codepoint)
|
||||
return this_codepoint + len;
|
||||
}
|
||||
|
||||
static char *get_previous_codepoint(struct fx_string_p *str, char *this_codepoint)
|
||||
static char *get_previous_codepoint(
|
||||
struct fx_string_p *str,
|
||||
char *this_codepoint)
|
||||
{
|
||||
char *start = string_ptr(str);
|
||||
char *end = this_codepoint - 1;
|
||||
@@ -260,7 +266,8 @@ static int string_change_capacity(struct fx_string_p *str, size_t capacity)
|
||||
}
|
||||
|
||||
if (!is_now_inline) {
|
||||
/* string was inline, and now large enough to require a buffer. */
|
||||
/* string was inline, and now large enough to require a buffer.
|
||||
*/
|
||||
return string_make_large(str, capacity);
|
||||
}
|
||||
|
||||
@@ -322,7 +329,10 @@ static fx_status string_reserve(struct fx_string_p *str, size_t capacity)
|
||||
}
|
||||
|
||||
static enum fx_status replace_ansi(
|
||||
struct fx_string_p *str, size_t start, size_t length, const char *new_data)
|
||||
struct fx_string_p *str,
|
||||
size_t start,
|
||||
size_t length,
|
||||
const char *new_data)
|
||||
{
|
||||
fx_status status = FX_SUCCESS;
|
||||
size_t new_data_len = strlen(new_data);
|
||||
@@ -361,7 +371,10 @@ static enum fx_status replace_ansi(
|
||||
}
|
||||
|
||||
static enum fx_status replace_utf8(
|
||||
struct fx_string_p *str, size_t start, size_t length, const char *new_data)
|
||||
struct fx_string_p *str,
|
||||
size_t start,
|
||||
size_t length,
|
||||
const char *new_data)
|
||||
{
|
||||
if (start >= str->s_codepoints) {
|
||||
return FX_ERR_INVALID_ARGUMENT;
|
||||
@@ -382,12 +395,17 @@ static enum fx_status replace_utf8(
|
||||
size_t old_data_offset = 0, old_data_nr_bytes = 0;
|
||||
size_t old_data_nr_codepoints = length;
|
||||
enum fx_status status = convert_codepoint_range_to_byte_range(
|
||||
str, start, length, &old_data_offset, &old_data_nr_bytes);
|
||||
str,
|
||||
start,
|
||||
length,
|
||||
&old_data_offset,
|
||||
&old_data_nr_bytes);
|
||||
if (!FX_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t new_total_bytes = str->s_len - old_data_nr_bytes + new_data_nr_bytes;
|
||||
size_t new_total_bytes
|
||||
= str->s_len - old_data_nr_bytes + new_data_nr_bytes;
|
||||
if (new_total_bytes > str->s_max) {
|
||||
status = string_reserve(str, new_total_bytes);
|
||||
}
|
||||
@@ -415,7 +433,10 @@ static enum fx_status replace_utf8(
|
||||
}
|
||||
|
||||
static fx_status string_replace(
|
||||
struct fx_string_p *str, size_t start, size_t length, const char *new_data)
|
||||
struct fx_string_p *str,
|
||||
size_t start,
|
||||
size_t length,
|
||||
const char *new_data)
|
||||
{
|
||||
if (str->s_len == str->s_codepoints) {
|
||||
return replace_ansi(str, start, length, new_data);
|
||||
@@ -424,7 +445,9 @@ static fx_status string_replace(
|
||||
return replace_utf8(str, start, length, new_data);
|
||||
}
|
||||
|
||||
static fx_status string_replace_all(struct fx_string_p *str, const char *new_data)
|
||||
static fx_status string_replace_all(
|
||||
struct fx_string_p *str,
|
||||
const char *new_data)
|
||||
{
|
||||
size_t new_len = strlen(new_data);
|
||||
string_reserve(str, new_len);
|
||||
@@ -437,7 +460,8 @@ static fx_status string_replace_all(struct fx_string_p *str, const char *new_dat
|
||||
}
|
||||
|
||||
static fx_status string_replace_all_with_stringstream(
|
||||
struct fx_string_p *str, const fx_stringstream *new_data)
|
||||
struct fx_string_p *str,
|
||||
const fx_stringstream *new_data)
|
||||
{
|
||||
size_t new_len = fx_stringstream_get_length(new_data);
|
||||
string_reserve(str, new_len);
|
||||
@@ -451,7 +475,10 @@ static fx_status string_replace_all_with_stringstream(
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status remove_ansi(struct fx_string_p *str, size_t start, size_t length)
|
||||
static enum fx_status remove_ansi(
|
||||
struct fx_string_p *str,
|
||||
size_t start,
|
||||
size_t length)
|
||||
{
|
||||
fx_status status = FX_SUCCESS;
|
||||
|
||||
@@ -479,11 +506,18 @@ static enum fx_status remove_ansi(struct fx_string_p *str, size_t start, size_t
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status remove_utf8(struct fx_string_p *str, size_t start, size_t length)
|
||||
static enum fx_status remove_utf8(
|
||||
struct fx_string_p *str,
|
||||
size_t start,
|
||||
size_t length)
|
||||
{
|
||||
size_t remove_offset = 0, remove_nr_bytes = 0;
|
||||
enum fx_status status = convert_codepoint_range_to_byte_range(
|
||||
str, start, length, &remove_offset, &remove_nr_bytes);
|
||||
str,
|
||||
start,
|
||||
length,
|
||||
&remove_offset,
|
||||
&remove_nr_bytes);
|
||||
if (!FX_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
@@ -506,7 +540,9 @@ static enum fx_status remove_utf8(struct fx_string_p *str, size_t start, size_t
|
||||
}
|
||||
|
||||
static enum fx_status string_remove(
|
||||
struct fx_string_p *str, size_t start, size_t length)
|
||||
struct fx_string_p *str,
|
||||
size_t start,
|
||||
size_t length)
|
||||
{
|
||||
if (str->s_len == str->s_codepoints) {
|
||||
return remove_ansi(str, start, length);
|
||||
@@ -515,7 +551,9 @@ static enum fx_status string_remove(
|
||||
return remove_utf8(str, start, length);
|
||||
}
|
||||
|
||||
static fx_status string_transform(struct fx_string_p *str, int (*transformer)(int))
|
||||
static fx_status string_transform(
|
||||
struct fx_string_p *str,
|
||||
int (*transformer)(int))
|
||||
{
|
||||
char *s = string_ptr(str);
|
||||
for (size_t i = 0; i < str->s_len; i++) {
|
||||
@@ -612,7 +650,10 @@ static fx_status string_trim(struct fx_string_p *str)
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_cstr_ansi(
|
||||
struct fx_string_p *dest, const char *src, size_t nr_bytes, size_t at)
|
||||
struct fx_string_p *dest,
|
||||
const char *src,
|
||||
size_t nr_bytes,
|
||||
size_t at)
|
||||
{
|
||||
if (at >= dest->s_len) {
|
||||
at = dest->s_len;
|
||||
@@ -637,7 +678,9 @@ static enum fx_status string_insert_cstr_ansi(
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_cstr_utf8(
|
||||
struct fx_string_p *dest, const char *src, size_t nr_bytes,
|
||||
struct fx_string_p *dest,
|
||||
const char *src,
|
||||
size_t nr_bytes,
|
||||
size_t codepoint_offset)
|
||||
{
|
||||
if (codepoint_offset >= dest->s_codepoints) {
|
||||
@@ -651,7 +694,11 @@ static enum fx_status string_insert_cstr_utf8(
|
||||
byte_offset = dest->s_len;
|
||||
} else {
|
||||
status = convert_codepoint_range_to_byte_range(
|
||||
dest, 0, codepoint_offset, NULL, &byte_offset);
|
||||
dest,
|
||||
0,
|
||||
codepoint_offset,
|
||||
NULL,
|
||||
&byte_offset);
|
||||
}
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
@@ -678,7 +725,10 @@ static enum fx_status string_insert_cstr_utf8(
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_wstr_ansi(
|
||||
struct fx_string_p *dest, const fx_wchar *src, size_t nr_codepoints, size_t at)
|
||||
struct fx_string_p *dest,
|
||||
const fx_wchar *src,
|
||||
size_t nr_codepoints,
|
||||
size_t at)
|
||||
{
|
||||
if (at >= dest->s_len) {
|
||||
at = dest->s_len;
|
||||
@@ -723,7 +773,9 @@ static enum fx_status string_insert_wstr_ansi(
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_wstr_utf8(
|
||||
struct fx_string_p *dest, const fx_wchar *src, size_t nr_codepoints,
|
||||
struct fx_string_p *dest,
|
||||
const fx_wchar *src,
|
||||
size_t nr_codepoints,
|
||||
size_t codepoint_offset)
|
||||
{
|
||||
if (codepoint_offset >= dest->s_codepoints) {
|
||||
@@ -748,7 +800,11 @@ static enum fx_status string_insert_wstr_utf8(
|
||||
move_offset = dest->s_len;
|
||||
} else {
|
||||
status = convert_codepoint_range_to_byte_range(
|
||||
dest, 0, codepoint_offset, NULL, &move_offset);
|
||||
dest,
|
||||
0,
|
||||
codepoint_offset,
|
||||
NULL,
|
||||
&move_offset);
|
||||
}
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
@@ -783,7 +839,10 @@ static enum fx_status string_insert_wstr_utf8(
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_cstr(
|
||||
struct fx_string_p *dest, const char *src, size_t nr_bytes, size_t at)
|
||||
struct fx_string_p *dest,
|
||||
const char *src,
|
||||
size_t nr_bytes,
|
||||
size_t at)
|
||||
{
|
||||
if (dest->s_len == dest->s_codepoints) {
|
||||
return string_insert_cstr_ansi(dest, src, nr_bytes, at);
|
||||
@@ -793,7 +852,10 @@ static enum fx_status string_insert_cstr(
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_wstr(
|
||||
struct fx_string_p *dest, const fx_wchar *src, size_t nr_codepoints, size_t at)
|
||||
struct fx_string_p *dest,
|
||||
const fx_wchar *src,
|
||||
size_t nr_codepoints,
|
||||
size_t at)
|
||||
{
|
||||
if (dest->s_len == dest->s_codepoints) {
|
||||
return string_insert_wstr_ansi(dest, src, nr_codepoints, at);
|
||||
@@ -803,25 +865,36 @@ static enum fx_status string_insert_wstr(
|
||||
}
|
||||
|
||||
static enum fx_status string_insertf(
|
||||
struct fx_string_p *dest, size_t at, const char *format, va_list arg)
|
||||
struct fx_string_p *dest,
|
||||
size_t at,
|
||||
const char *format,
|
||||
va_list arg)
|
||||
{
|
||||
char buf[1024];
|
||||
size_t len = vsnprintf(buf, sizeof buf, format, arg);
|
||||
return string_insert_cstr(dest, buf, len, at);
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_c(struct fx_string_p *dest, char c, size_t at)
|
||||
static enum fx_status string_insert_c(
|
||||
struct fx_string_p *dest,
|
||||
char c,
|
||||
size_t at)
|
||||
{
|
||||
return string_insert_cstr(dest, &c, 1, at);
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_wc(struct fx_string_p *dest, fx_wchar c, size_t at)
|
||||
static enum fx_status string_insert_wc(
|
||||
struct fx_string_p *dest,
|
||||
fx_wchar c,
|
||||
size_t at)
|
||||
{
|
||||
return string_insert_wstr(dest, &c, 1, at);
|
||||
}
|
||||
|
||||
static enum fx_status string_insert_s(
|
||||
struct fx_string_p *dest, const struct fx_string_p *src, size_t at)
|
||||
struct fx_string_p *dest,
|
||||
const struct fx_string_p *src,
|
||||
size_t at)
|
||||
{
|
||||
return string_insert_cstr(dest, string_ptr(src), src->s_len, at);
|
||||
}
|
||||
@@ -858,7 +931,9 @@ static bool has_prefix(const char *s, const char *prefix, size_t *prefix_len)
|
||||
}
|
||||
|
||||
static bool has_prefixes(
|
||||
const char *s, const char **prefixes, size_t nr_prefixes,
|
||||
const char *s,
|
||||
const char **prefixes,
|
||||
size_t nr_prefixes,
|
||||
size_t *selected_prefix_len)
|
||||
{
|
||||
for (size_t i = 0; i < nr_prefixes; i++) {
|
||||
@@ -929,14 +1004,16 @@ static enum fx_status find_next_token(struct fx_string_iterator_p *it)
|
||||
}
|
||||
|
||||
it->_ds = offset + prefix_len;
|
||||
it->string_value = fx_string_ptr(it->_tmp);
|
||||
it->string_value = fx_string_get_cstr(it->_tmp);
|
||||
it->string_length = it->_tmp_p->s_len;
|
||||
it->string_codepoints = it->_tmp_p->s_codepoints;
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_iterator *string_tokenise(
|
||||
struct fx_string_p *str, const char *delims[], size_t nr_delims,
|
||||
struct fx_string_p *str,
|
||||
const char *delims[],
|
||||
size_t nr_delims,
|
||||
fx_string_tokenise_flags flags)
|
||||
{
|
||||
if (!nr_delims) {
|
||||
@@ -970,7 +1047,9 @@ static fx_iterator *string_tokenise(
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
static size_t string_get_size(const struct fx_string_p *str, fx_strlen_flags flags)
|
||||
static size_t string_get_size(
|
||||
const struct fx_string_p *str,
|
||||
fx_strlen_flags flags)
|
||||
{
|
||||
switch (flags) {
|
||||
case FX_STRLEN_NORMAL:
|
||||
@@ -987,7 +1066,9 @@ static size_t string_get_capacity(const struct fx_string_p *str)
|
||||
return str->s_max;
|
||||
}
|
||||
|
||||
static bool string_compare(const struct fx_string_p *a, const struct fx_string_p *b)
|
||||
static bool string_compare(
|
||||
const struct fx_string_p *a,
|
||||
const struct fx_string_p *b)
|
||||
{
|
||||
if (a->s_len != b->s_len) {
|
||||
return false;
|
||||
@@ -1041,7 +1122,10 @@ static void string_pop_back(struct fx_string_p *str)
|
||||
str->s_len--;
|
||||
}
|
||||
|
||||
static fx_string *string_substr(const struct fx_string_p *str, size_t start, size_t len)
|
||||
static fx_string *string_substr(
|
||||
const struct fx_string_p *str,
|
||||
size_t start,
|
||||
size_t len)
|
||||
{
|
||||
if (start > string_get_size(str, FX_STRLEN_NORMAL)) {
|
||||
return NULL;
|
||||
@@ -1052,7 +1136,8 @@ static fx_string *string_substr(const struct fx_string_p *str, size_t start, siz
|
||||
}
|
||||
|
||||
fx_string *newstr = fx_string_create();
|
||||
struct fx_string_p *newstr_p = fx_object_get_private(newstr, FX_TYPE_STRING);
|
||||
struct fx_string_p *newstr_p
|
||||
= fx_object_get_private(newstr, FX_TYPE_STRING);
|
||||
string_reserve(newstr_p, len);
|
||||
|
||||
const char *src = string_ptr(str) + start;
|
||||
@@ -1146,32 +1231,57 @@ fx_status fx_string_reserve(fx_string *str, size_t capacity)
|
||||
}
|
||||
|
||||
fx_status fx_string_replace(
|
||||
fx_string *str, size_t start, size_t length, const char *new_data)
|
||||
fx_string *str,
|
||||
size_t start,
|
||||
size_t length,
|
||||
const char *new_data)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING, string_replace, str, start, length, new_data);
|
||||
FX_TYPE_STRING,
|
||||
string_replace,
|
||||
str,
|
||||
start,
|
||||
length,
|
||||
new_data);
|
||||
}
|
||||
|
||||
fx_status fx_string_replace_all(fx_string *str, const char *new_data)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_STRING, string_replace_all, str, new_data);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING,
|
||||
string_replace_all,
|
||||
str,
|
||||
new_data);
|
||||
}
|
||||
|
||||
fx_status fx_string_replace_all_with_stringstream(
|
||||
fx_string *str, const fx_stringstream *new_data)
|
||||
fx_string *str,
|
||||
const fx_stringstream *new_data)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING, string_replace_all_with_stringstream, str, new_data);
|
||||
FX_TYPE_STRING,
|
||||
string_replace_all_with_stringstream,
|
||||
str,
|
||||
new_data);
|
||||
}
|
||||
|
||||
enum fx_status fx_string_remove(fx_string *str, size_t start, size_t length)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_STRING, string_remove, str, start, length);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING,
|
||||
string_remove,
|
||||
str,
|
||||
start,
|
||||
length);
|
||||
}
|
||||
|
||||
fx_status fx_string_transform(fx_string *str, int (*transformer)(int))
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_STRING, string_transform, str, transformer);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING,
|
||||
string_transform,
|
||||
str,
|
||||
transformer);
|
||||
}
|
||||
|
||||
fx_status fx_string_trim(fx_string *str)
|
||||
@@ -1189,29 +1299,46 @@ enum fx_status fx_string_insert_wc(fx_string *dest, fx_wchar c, size_t at)
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_STRING, string_insert_wc, dest, c, at);
|
||||
}
|
||||
|
||||
enum fx_status fx_string_insert_s(fx_string *dest, const fx_string *src, size_t at)
|
||||
enum fx_status fx_string_insert_s(
|
||||
fx_string *dest,
|
||||
const fx_string *src,
|
||||
size_t at)
|
||||
{
|
||||
struct fx_string_p *dest_p = fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
const struct fx_string_p *src_p = fx_object_get_private(src, FX_TYPE_STRING);
|
||||
struct fx_string_p *dest_p
|
||||
= fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
const struct fx_string_p *src_p
|
||||
= fx_object_get_private(src, FX_TYPE_STRING);
|
||||
return string_insert_s(dest_p, src_p, at);
|
||||
}
|
||||
|
||||
enum fx_status fx_string_insert_cstr(fx_string *dest, const char *src, size_t at)
|
||||
enum fx_status fx_string_insert_cstr(
|
||||
fx_string *dest,
|
||||
const char *src,
|
||||
size_t at)
|
||||
{
|
||||
struct fx_string_p *dest_p = fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
struct fx_string_p *dest_p
|
||||
= fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
return string_insert_cstr(dest_p, src, strlen(src), at);
|
||||
}
|
||||
|
||||
enum fx_status fx_string_insert_wstr(fx_string *dest, const fx_wchar *src, size_t at)
|
||||
enum fx_status fx_string_insert_wstr(
|
||||
fx_string *dest,
|
||||
const fx_wchar *src,
|
||||
size_t at)
|
||||
{
|
||||
struct fx_string_p *dest_p = fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
struct fx_string_p *dest_p
|
||||
= fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
return string_insert_wstr(dest_p, src, fx_wstrlen(src), at);
|
||||
}
|
||||
|
||||
enum fx_status fx_string_insert_cstrf(
|
||||
fx_string *dest, size_t at, const char *format, ...)
|
||||
fx_string *dest,
|
||||
size_t at,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
struct fx_string_p *dest_p = fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
struct fx_string_p *dest_p
|
||||
= fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
@@ -1222,15 +1349,24 @@ enum fx_status fx_string_insert_cstrf(
|
||||
}
|
||||
|
||||
enum fx_status fx_string_insert_cstrn(
|
||||
fx_string *dest, const char *src, size_t len, size_t at)
|
||||
fx_string *dest,
|
||||
const char *src,
|
||||
size_t len,
|
||||
size_t at)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING, string_insert_cstr, dest, src, len, at);
|
||||
FX_TYPE_STRING,
|
||||
string_insert_cstr,
|
||||
dest,
|
||||
src,
|
||||
len,
|
||||
at);
|
||||
}
|
||||
|
||||
enum fx_status fx_string_append_cstrf(fx_string *dest, const char *format, ...)
|
||||
{
|
||||
struct fx_string_p *dest_p = fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
struct fx_string_p *dest_p
|
||||
= fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
@@ -1242,7 +1378,8 @@ enum fx_status fx_string_append_cstrf(fx_string *dest, const char *format, ...)
|
||||
|
||||
enum fx_status fx_string_prepend_cstrf(fx_string *dest, const char *format, ...)
|
||||
{
|
||||
struct fx_string_p *dest_p = fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
struct fx_string_p *dest_p
|
||||
= fx_object_get_private(dest, FX_TYPE_STRING);
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
@@ -1258,11 +1395,18 @@ void fx_string_clear(fx_string *str)
|
||||
}
|
||||
|
||||
fx_iterator *fx_string_tokenise(
|
||||
fx_string *str, const char *delims[], size_t nr_delims,
|
||||
fx_string *str,
|
||||
const char *delims[],
|
||||
size_t nr_delims,
|
||||
fx_string_tokenise_flags flags)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING, string_tokenise, str, delims, nr_delims, flags);
|
||||
FX_TYPE_STRING,
|
||||
string_tokenise,
|
||||
str,
|
||||
delims,
|
||||
nr_delims,
|
||||
flags);
|
||||
}
|
||||
|
||||
size_t fx_string_get_size(const fx_string *str, fx_strlen_flags flags)
|
||||
@@ -1282,12 +1426,12 @@ bool fx_string_compare(const fx_string *a, const fx_string *b)
|
||||
return string_compare(ap, bp);
|
||||
}
|
||||
|
||||
char fx_string_front(const fx_string *str)
|
||||
char fx_string_get_first_char(const fx_string *str)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_STRING, string_front, str);
|
||||
}
|
||||
|
||||
char fx_string_back(const fx_string *str)
|
||||
char fx_string_get_last_char(const fx_string *str)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_STRING, string_back, str);
|
||||
}
|
||||
@@ -1297,14 +1441,19 @@ void fx_string_pop_back(fx_string *str)
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_STRING, string_pop_back, str);
|
||||
}
|
||||
|
||||
const char *fx_string_ptr(const fx_string *str)
|
||||
const char *fx_string_get_cstr(const fx_string *str)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_STRING, string_ptr, str);
|
||||
}
|
||||
|
||||
fx_string *fx_string_substr(const fx_string *str, size_t start, size_t len)
|
||||
fx_string *fx_string_get_substr(const fx_string *str, size_t start, size_t len)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_STRING, string_substr, str, start, len);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_STRING,
|
||||
string_substr,
|
||||
str,
|
||||
start,
|
||||
len);
|
||||
}
|
||||
|
||||
uint64_t fx_string_hash(const fx_string *str)
|
||||
@@ -1495,12 +1644,14 @@ static enum fx_status iterator_move_next(const fx_iterator *obj)
|
||||
}
|
||||
}
|
||||
|
||||
static fx_iterator_value chars_iterator_get_value(struct fx_string_iterator_p *it)
|
||||
static fx_iterator_value chars_iterator_get_value(
|
||||
struct fx_string_iterator_p *it)
|
||||
{
|
||||
return FX_ITERATOR_VALUE_INT(it->char_value);
|
||||
}
|
||||
|
||||
static fx_iterator_value tokens_iterator_get_value(struct fx_string_iterator_p *it)
|
||||
static fx_iterator_value tokens_iterator_get_value(
|
||||
struct fx_string_iterator_p *it)
|
||||
{
|
||||
return FX_ITERATOR_VALUE_CPTR(it->string_value);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <ctype.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/ds/uuid.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -15,31 +15,43 @@ struct fx_uuid_p {
|
||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||
|
||||
static fx_status uuid_to_cstr(
|
||||
const struct fx_uuid_p *uuid, char out[FX_UUID_STRING_MAX])
|
||||
const struct fx_uuid_p *uuid,
|
||||
char out[FX_UUID_STRING_MAX])
|
||||
{
|
||||
snprintf(
|
||||
out, FX_UUID_STRING_MAX,
|
||||
out,
|
||||
FX_UUID_STRING_MAX,
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%"
|
||||
"02x%02x",
|
||||
uuid->uuid_bytes.uuid_bytes[0], uuid->uuid_bytes.uuid_bytes[1],
|
||||
uuid->uuid_bytes.uuid_bytes[2], uuid->uuid_bytes.uuid_bytes[3],
|
||||
uuid->uuid_bytes.uuid_bytes[4], uuid->uuid_bytes.uuid_bytes[5],
|
||||
uuid->uuid_bytes.uuid_bytes[6], uuid->uuid_bytes.uuid_bytes[7],
|
||||
uuid->uuid_bytes.uuid_bytes[8], uuid->uuid_bytes.uuid_bytes[9],
|
||||
uuid->uuid_bytes.uuid_bytes[10], uuid->uuid_bytes.uuid_bytes[11],
|
||||
uuid->uuid_bytes.uuid_bytes[12], uuid->uuid_bytes.uuid_bytes[13],
|
||||
uuid->uuid_bytes.uuid_bytes[14], uuid->uuid_bytes.uuid_bytes[15]);
|
||||
uuid->uuid_bytes.uuid_bytes[0],
|
||||
uuid->uuid_bytes.uuid_bytes[1],
|
||||
uuid->uuid_bytes.uuid_bytes[2],
|
||||
uuid->uuid_bytes.uuid_bytes[3],
|
||||
uuid->uuid_bytes.uuid_bytes[4],
|
||||
uuid->uuid_bytes.uuid_bytes[5],
|
||||
uuid->uuid_bytes.uuid_bytes[6],
|
||||
uuid->uuid_bytes.uuid_bytes[7],
|
||||
uuid->uuid_bytes.uuid_bytes[8],
|
||||
uuid->uuid_bytes.uuid_bytes[9],
|
||||
uuid->uuid_bytes.uuid_bytes[10],
|
||||
uuid->uuid_bytes.uuid_bytes[11],
|
||||
uuid->uuid_bytes.uuid_bytes[12],
|
||||
uuid->uuid_bytes.uuid_bytes[13],
|
||||
uuid->uuid_bytes.uuid_bytes[14],
|
||||
uuid->uuid_bytes.uuid_bytes[15]);
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static void uuid_get_bytes(
|
||||
const struct fx_uuid_p *uuid, unsigned char bytes[FX_UUID_NBYTES])
|
||||
const struct fx_uuid_p *uuid,
|
||||
unsigned char bytes[FX_UUID_NBYTES])
|
||||
{
|
||||
memcpy(bytes, uuid->uuid_bytes.uuid_bytes, FX_UUID_NBYTES);
|
||||
}
|
||||
|
||||
static void uuid_get_uuid_bytes(
|
||||
const struct fx_uuid_p *uuid, union fx_uuid_bytes *bytes)
|
||||
const struct fx_uuid_p *uuid,
|
||||
union fx_uuid_bytes *bytes)
|
||||
{
|
||||
memcpy(bytes, &uuid->uuid_bytes, sizeof *bytes);
|
||||
}
|
||||
@@ -52,11 +64,22 @@ static union fx_uuid_bytes *uuid_ptr(struct fx_uuid_p *uuid)
|
||||
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
fx_uuid *fx_uuid_create_from_bytes(
|
||||
unsigned char u00, unsigned char u01, unsigned char u02,
|
||||
unsigned char u03, unsigned char u04, unsigned char u05,
|
||||
unsigned char u06, unsigned char u07, unsigned char u08,
|
||||
unsigned char u09, unsigned char u10, unsigned char u11,
|
||||
unsigned char u12, unsigned char u13, unsigned char u14, unsigned char u15)
|
||||
unsigned char u00,
|
||||
unsigned char u01,
|
||||
unsigned char u02,
|
||||
unsigned char u03,
|
||||
unsigned char u04,
|
||||
unsigned char u05,
|
||||
unsigned char u06,
|
||||
unsigned char u07,
|
||||
unsigned char u08,
|
||||
unsigned char u09,
|
||||
unsigned char u10,
|
||||
unsigned char u11,
|
||||
unsigned char u12,
|
||||
unsigned char u13,
|
||||
unsigned char u14,
|
||||
unsigned char u15)
|
||||
{
|
||||
fx_uuid *uuid = fx_uuid_create();
|
||||
if (!uuid) {
|
||||
@@ -171,7 +194,11 @@ void fx_uuid_get_bytes(const fx_uuid *uuid, unsigned char bytes[FX_UUID_NBYTES])
|
||||
|
||||
void fx_uuid_get_uuid_bytes(const fx_uuid *uuid, union fx_uuid_bytes *bytes)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_UUID, uuid_get_uuid_bytes, uuid, bytes);
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_UUID,
|
||||
uuid_get_uuid_bytes,
|
||||
uuid,
|
||||
bytes);
|
||||
}
|
||||
|
||||
union fx_uuid_bytes *fx_uuid_ptr(fx_uuid *uuid)
|
||||
@@ -188,7 +215,7 @@ fx_uuid *fx_uuid_create_from_uuid_bytes(const union fx_uuid_bytes *bytes)
|
||||
|
||||
fx_uuid *fx_uuid_create_from_string(const fx_string *string)
|
||||
{
|
||||
return fx_uuid_create_from_cstr(fx_string_ptr(string));
|
||||
return fx_uuid_create_from_cstr(fx_string_get_cstr(string));
|
||||
}
|
||||
|
||||
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||
@@ -207,7 +234,7 @@ static void uuid_to_string(const fx_object *uuid, fx_stream *out)
|
||||
{
|
||||
char str[FX_UUID_STRING_MAX];
|
||||
fx_uuid_to_cstr(uuid, str);
|
||||
fx_stream_write_string(out, str, NULL);
|
||||
fx_stream_write_cstr(out, str, NULL);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
@@ -75,7 +75,7 @@ static fx_result file_open_shadow(
|
||||
|
||||
fx_string_prepend_cstr(filename, ".~");
|
||||
|
||||
fx_path *shadow_filename = fx_path_create_from_cstr(fx_string_ptr(filename));
|
||||
fx_path *shadow_filename = fx_path_create_from_cstr(fx_string_get_cstr(filename));
|
||||
fx_string_unref(filename);
|
||||
|
||||
const fx_path *parts[] = {
|
||||
|
||||
+11
-11
@@ -36,13 +36,13 @@ static fx_path *path_make_canonical(const struct fx_path_p *in)
|
||||
|
||||
static bool path_is_absolute(const struct fx_path_p *path)
|
||||
{
|
||||
const char *s = fx_string_ptr(path->p_pathstr);
|
||||
const char *s = fx_string_get_cstr(path->p_pathstr);
|
||||
return s[0] == '/';
|
||||
}
|
||||
|
||||
static const char *path_ptr(const struct fx_path_p *path)
|
||||
{
|
||||
return fx_string_ptr(path->p_pathstr);
|
||||
return fx_string_get_cstr(path->p_pathstr);
|
||||
}
|
||||
|
||||
static enum fx_status path_stat(const struct fx_path_p *path, struct fx_file_info *out)
|
||||
@@ -98,8 +98,8 @@ static void append_path(struct fx_path_p *dest, const struct fx_path_p *src)
|
||||
}
|
||||
|
||||
if (fx_string_get_size(dest->p_pathstr, FX_STRLEN_NORMAL) > 0
|
||||
&& fx_string_back(dest->p_pathstr) != '/'
|
||||
&& fx_string_front(src->p_pathstr) != '/') {
|
||||
&& fx_string_get_last_char(dest->p_pathstr) != '/'
|
||||
&& fx_string_get_first_char(src->p_pathstr) != '/') {
|
||||
char s[] = {'/', 0};
|
||||
fx_string_append_cstr(dest->p_pathstr, s);
|
||||
}
|
||||
@@ -109,7 +109,7 @@ static void append_path(struct fx_path_p *dest, const struct fx_path_p *src)
|
||||
|
||||
static enum fx_status path_unlink(const struct fx_path_p *path)
|
||||
{
|
||||
int err = remove(fx_string_ptr(path->p_pathstr));
|
||||
int err = remove(fx_string_get_cstr(path->p_pathstr));
|
||||
return err == 0 ? FX_SUCCESS : fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ static enum fx_status path_get_directory(
|
||||
fx_string *path_str = path->p_pathstr;
|
||||
long len = fx_string_get_size(path_str, FX_STRLEN_NORMAL);
|
||||
|
||||
const char *path_cstr = fx_string_ptr(path_str);
|
||||
const char *path_cstr = fx_string_get_cstr(path_str);
|
||||
char *sep = strrchr(path_cstr, '/');
|
||||
|
||||
if (!sep) {
|
||||
@@ -128,9 +128,9 @@ static enum fx_status path_get_directory(
|
||||
}
|
||||
|
||||
size_t dir_path_len = (size_t)(sep - path_cstr);
|
||||
fx_string *dir_path_s = fx_string_substr(path_str, 0, dir_path_len);
|
||||
fx_string *dir_path_s = fx_string_get_substr(path_str, 0, dir_path_len);
|
||||
|
||||
fx_path *dir_path = fx_path_create_from_cstr(fx_string_ptr(dir_path_s));
|
||||
fx_path *dir_path = fx_path_create_from_cstr(fx_string_get_cstr(dir_path_s));
|
||||
fx_string_unref(dir_path_s);
|
||||
|
||||
*out_dir_path = dir_path;
|
||||
@@ -144,7 +144,7 @@ static enum fx_status path_get_filename(
|
||||
fx_string *path_str = path->p_pathstr;
|
||||
long len = fx_string_get_size(path_str, FX_STRLEN_NORMAL);
|
||||
|
||||
char *sep = strrchr(fx_string_ptr(path_str), '/');
|
||||
char *sep = strrchr(fx_string_get_cstr(path_str), '/');
|
||||
|
||||
if (!sep) {
|
||||
fx_string_append_s(out_name, path_str);
|
||||
@@ -245,7 +245,7 @@ fx_path *fx_path_create_from_cstr(const char *cstr)
|
||||
prev = c;
|
||||
}
|
||||
|
||||
while (fx_string_back(p->p_pathstr) == '/') {
|
||||
while (fx_string_get_last_char(p->p_pathstr) == '/') {
|
||||
fx_string_pop_back(p->p_pathstr);
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ void path_to_string(const fx_object *obj, fx_stream *out)
|
||||
{
|
||||
struct fx_path_p *path = fx_object_get_private(obj, FX_TYPE_PATH);
|
||||
|
||||
fx_stream_write_string(out, fx_string_ptr(path->p_pathstr), NULL);
|
||||
fx_stream_write_cstr(out, fx_string_get_cstr(path->p_pathstr), NULL);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
@@ -0,0 +1,689 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include "misc.h"
|
||||
#include "posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#include <fx/core/error.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/io/directory.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*** PRIVATE DATA *************************************************************/
|
||||
|
||||
enum directory_flags {
|
||||
DIRECTORY_DELETE_ON_CLOSE = 0x01u,
|
||||
};
|
||||
|
||||
struct fx_directory_p {
|
||||
enum directory_flags d_flags;
|
||||
int d_fd;
|
||||
fx_path *d_path_rel;
|
||||
fx_path *d_path_abs;
|
||||
};
|
||||
|
||||
struct fx_directory_iterator_p {
|
||||
struct fx_directory_p *_p;
|
||||
|
||||
FTS *fts;
|
||||
FTSENT *ent;
|
||||
|
||||
fx_directory_iterator_flags flags;
|
||||
fx_directory *root;
|
||||
|
||||
fx_directory_entry entry;
|
||||
};
|
||||
|
||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||
static const fx_path *directory_get_path(const struct fx_directory_p *dir)
|
||||
{
|
||||
return dir->d_path_abs;
|
||||
}
|
||||
|
||||
static const fx_path *directory_get_rel_path(const struct fx_directory_p *dir)
|
||||
{
|
||||
return dir->d_path_rel;
|
||||
}
|
||||
|
||||
static const char *directory_get_path_cstr(const struct fx_directory_p *dir)
|
||||
{
|
||||
return fx_path_ptr(dir->d_path_abs);
|
||||
}
|
||||
|
||||
static const char *directory_get_rel_path_cstr(const struct fx_directory_p *dir)
|
||||
{
|
||||
return fx_path_ptr(dir->d_path_rel);
|
||||
}
|
||||
|
||||
static fx_result directory_delete(fx_directory *dir, struct fx_directory_p *dir_p)
|
||||
{
|
||||
enum fx_status status = FX_SUCCESS;
|
||||
|
||||
fx_iterator *it
|
||||
= fx_directory_begin(dir, FX_DIRECTORY_ITERATE_PARENT_LAST);
|
||||
while (FX_OK(fx_iterator_get_status(it))) {
|
||||
fx_iterator_erase(it);
|
||||
}
|
||||
|
||||
status = fx_iterator_get_status(it);
|
||||
if (!FX_OK(status) && status != FX_ERR_NO_DATA) {
|
||||
return FX_RESULT_STATUS(status);
|
||||
}
|
||||
|
||||
status = fx_path_unlink(dir_p->d_path_abs);
|
||||
if (!FX_OK(status)) {
|
||||
return FX_RESULT_STATUS(status);
|
||||
}
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static bool directory_path_exists(
|
||||
const struct fx_directory_p *root, const fx_path *path)
|
||||
{
|
||||
const fx_path *parts[] = {
|
||||
root ? root->d_path_abs : NULL,
|
||||
path,
|
||||
};
|
||||
|
||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
if (!abs_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = fx_path_exists(abs_path);
|
||||
fx_path_unref(abs_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool directory_path_is_file(
|
||||
const struct fx_directory_p *root, const fx_path *path)
|
||||
{
|
||||
const fx_path *parts[] = {
|
||||
root ? root->d_path_abs : NULL,
|
||||
path,
|
||||
};
|
||||
|
||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
if (!abs_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = fx_path_is_file(abs_path);
|
||||
fx_path_unref(abs_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool directory_path_is_directory(
|
||||
const struct fx_directory_p *root, const fx_path *path)
|
||||
{
|
||||
const fx_path *parts[] = {
|
||||
root ? root->d_path_abs : NULL,
|
||||
path,
|
||||
};
|
||||
|
||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
if (!abs_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = fx_path_is_directory(abs_path);
|
||||
fx_path_unref(abs_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static fx_result directory_path_stat(
|
||||
const struct fx_directory_p *root, const fx_path *path,
|
||||
struct fx_file_info *out)
|
||||
{
|
||||
const fx_path *parts[] = {
|
||||
root ? root->d_path_abs : NULL,
|
||||
path,
|
||||
};
|
||||
|
||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
if (!abs_path) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
enum fx_status status = fx_path_stat(abs_path, out);
|
||||
fx_path_unref(abs_path);
|
||||
|
||||
return FX_RESULT_STATUS(status);
|
||||
}
|
||||
|
||||
static fx_result directory_path_unlink(
|
||||
const struct fx_directory_p *root, const fx_path *path)
|
||||
{
|
||||
const fx_path *parts[] = {
|
||||
root ? root->d_path_abs : NULL,
|
||||
path,
|
||||
};
|
||||
|
||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
if (!abs_path) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
enum fx_status status = fx_path_unlink(abs_path);
|
||||
fx_path_unref(abs_path);
|
||||
|
||||
return FX_RESULT_STATUS(status);
|
||||
}
|
||||
|
||||
static fx_result create_directory(struct fx_directory_p *root, const char *path)
|
||||
{
|
||||
int root_fd = root ? root->d_fd : -1;
|
||||
int err;
|
||||
|
||||
if (root_fd == -1) {
|
||||
err = mkdir(path, 0755);
|
||||
} else {
|
||||
err = mkdirat(root_fd, path, 0755);
|
||||
}
|
||||
|
||||
if (err == 0 || errno == EEXIST) {
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
return fx_result_from_errno_with_subfilepath(
|
||||
errno, path, directory_get_rel_path_cstr(root), FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
static fx_result create_directory_hierarchy(
|
||||
struct fx_directory_p *root, const char *path)
|
||||
{
|
||||
int root_fd = root ? root->d_fd : AT_FDCWD;
|
||||
|
||||
char *path_buf = fx_strdup(path);
|
||||
if (!path_buf) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
fx_result result = FX_RESULT_SUCCESS;
|
||||
for (size_t i = 0; path_buf[i]; i++) {
|
||||
if (path_buf[i] != '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
path_buf[i] = 0;
|
||||
|
||||
int err = mkdirat(root_fd, path_buf, 0755);
|
||||
if (err != 0 && errno != EEXIST) {
|
||||
result = fx_result_from_errno_with_subfilepath(
|
||||
errno, path_buf, directory_get_rel_path_cstr(root),
|
||||
FX_ERR_IO_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
path_buf[i] = '/';
|
||||
}
|
||||
|
||||
int err = mkdirat(root_fd, path_buf, 0755);
|
||||
if (err != 0 && errno != EEXIST) {
|
||||
result = fx_result_from_errno_with_subfilepath(
|
||||
errno, path_buf, directory_get_rel_path_cstr(root),
|
||||
FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
free(path_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
static fx_result directory_open(
|
||||
struct fx_directory_p *root, const fx_path *path,
|
||||
fx_directory_open_flags flags, fx_directory **out)
|
||||
{
|
||||
enum fx_status status = FX_SUCCESS;
|
||||
|
||||
int root_fd = root ? root->d_fd : AT_FDCWD;
|
||||
|
||||
const char *path_cstr = fx_path_ptr(path);
|
||||
if (root) {
|
||||
while (*path_cstr == '/') {
|
||||
path_cstr++;
|
||||
}
|
||||
}
|
||||
|
||||
fx_result result = FX_RESULT_SUCCESS;
|
||||
if ((flags & FX_DIRECTORY_OPEN_CREATE_INTERMEDIATE)
|
||||
== FX_DIRECTORY_OPEN_CREATE_INTERMEDIATE) {
|
||||
result = create_directory_hierarchy(root, path_cstr);
|
||||
} else if ((flags & FX_DIRECTORY_OPEN_CREATE) == FX_DIRECTORY_OPEN_CREATE) {
|
||||
result = create_directory(root, path_cstr);
|
||||
}
|
||||
|
||||
if (fx_result_is_error(result)) {
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
int fd = openat(root_fd, path_cstr, O_DIRECTORY);
|
||||
|
||||
if (fd == -1) {
|
||||
status = fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
return FX_RESULT_STATUS(status);
|
||||
}
|
||||
|
||||
fx_directory *dir = fx_object_create(FX_TYPE_DIRECTORY);
|
||||
fx_path *cwd = NULL;
|
||||
struct fx_directory_p *p = fx_object_get_private(dir, FX_TYPE_DIRECTORY);
|
||||
|
||||
if (!root) {
|
||||
cwd = fx_path_create_cwd();
|
||||
}
|
||||
|
||||
const fx_path *parts[] = {
|
||||
root ? root->d_path_abs : cwd,
|
||||
path,
|
||||
};
|
||||
|
||||
fx_path *new_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
if (!new_path) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
if (cwd) {
|
||||
fx_path_unref(cwd);
|
||||
}
|
||||
|
||||
p->d_path_abs = new_path;
|
||||
p->d_path_rel = fx_path_duplicate(path);
|
||||
p->d_fd = fd;
|
||||
|
||||
if (flags & FX_DIRECTORY_OPEN_DELETE_ON_CLOSE) {
|
||||
p->d_flags = DIRECTORY_DELETE_ON_CLOSE;
|
||||
}
|
||||
|
||||
*out = dir;
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
fx_result fx_directory_open(
|
||||
fx_directory *root, const fx_path *path, fx_directory_open_flags flags,
|
||||
fx_directory **out)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_DIRECTORY, directory_open, root, path, flags, out);
|
||||
}
|
||||
|
||||
fx_result fx_directory_open_temp(fx_directory **out)
|
||||
{
|
||||
char name[16];
|
||||
char path[128];
|
||||
|
||||
while (1) {
|
||||
z__fx_io_generate_tmp_filename(name, sizeof name);
|
||||
snprintf(path, sizeof path, "/tmp/%s", name);
|
||||
fx_path *rpath = fx_path_create_from_cstr(path);
|
||||
|
||||
fx_directory *dir = NULL;
|
||||
fx_result status = fx_directory_open(
|
||||
FX_DIRECTORY_ROOT, rpath, FX_DIRECTORY_OPEN_CREATE, &dir);
|
||||
struct fx_directory_p *p
|
||||
= fx_object_get_private(dir, FX_TYPE_DIRECTORY);
|
||||
|
||||
if (fx_error_get_status_code(status) == FX_ERR_NAME_EXISTS) {
|
||||
fx_path_unref(rpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
p->d_flags |= DIRECTORY_DELETE_ON_CLOSE;
|
||||
}
|
||||
|
||||
fx_path_unlink(rpath);
|
||||
fx_path_unref(rpath);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
const fx_path *fx_directory_get_path(const fx_directory *dir)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DIRECTORY, directory_get_path, dir);
|
||||
}
|
||||
|
||||
const fx_path *fx_directory_get_rel_path(const fx_directory *dir)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DIRECTORY, directory_get_rel_path, dir);
|
||||
}
|
||||
|
||||
const char *fx_directory_get_path_cstr(const fx_directory *dir)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DIRECTORY, directory_get_path_cstr, dir);
|
||||
}
|
||||
|
||||
const char *fx_directory_get_rel_path_cstr(const fx_directory *dir)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(
|
||||
FX_TYPE_DIRECTORY, directory_get_rel_path_cstr, dir);
|
||||
}
|
||||
|
||||
fx_result fx_directory_delete(fx_directory *dir)
|
||||
{
|
||||
struct fx_directory_p *p = fx_object_get_private(dir, FX_TYPE_DIRECTORY);
|
||||
p->d_flags |= DIRECTORY_DELETE_ON_CLOSE;
|
||||
/* TODO allow object release functions to return a fx_result value */
|
||||
fx_directory_unref(dir);
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
bool fx_directory_path_exists(const fx_directory *root, const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_DIRECTORY, directory_path_exists, root, path);
|
||||
}
|
||||
|
||||
bool fx_directory_path_is_file(const fx_directory *root, const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_DIRECTORY, directory_path_is_file, root, path);
|
||||
}
|
||||
|
||||
bool fx_directory_path_is_directory(const fx_directory *root, const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_DIRECTORY, directory_path_is_directory, root, path);
|
||||
}
|
||||
|
||||
fx_result fx_directory_path_stat(
|
||||
const fx_directory *root, const fx_path *path, struct fx_file_info *out)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_DIRECTORY, directory_path_stat, root, path, out);
|
||||
}
|
||||
|
||||
fx_result fx_directory_path_unlink(const fx_directory *root, const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_DIRECTORY, directory_path_unlink, root, path);
|
||||
}
|
||||
|
||||
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||
|
||||
static void directory_init(fx_object *obj, void *priv)
|
||||
{
|
||||
struct fx_directory_p *dir = priv;
|
||||
}
|
||||
|
||||
static void directory_fini(fx_object *obj, void *priv)
|
||||
{
|
||||
struct fx_directory_p *dir = priv;
|
||||
|
||||
close(dir->d_fd);
|
||||
|
||||
if (dir->d_flags & DIRECTORY_DELETE_ON_CLOSE) {
|
||||
directory_delete(obj, dir);
|
||||
}
|
||||
|
||||
fx_path_unref(dir->d_path_abs);
|
||||
}
|
||||
|
||||
/*** ITERATOR FUNCTIONS *******************************************************/
|
||||
|
||||
static int ftsent_compare(const FTSENT **one, const FTSENT **two)
|
||||
{
|
||||
return (strcmp((*one)->fts_name, (*two)->fts_name));
|
||||
}
|
||||
|
||||
static void update_iterator_data(struct fx_directory_iterator_p *it)
|
||||
{
|
||||
if (it->entry.filepath) {
|
||||
fx_path_unref((fx_path *)it->entry.filepath);
|
||||
it->entry.filepath = NULL;
|
||||
}
|
||||
|
||||
FTSENT *ent = it->ent;
|
||||
|
||||
fx_path *path = fx_path_create_from_cstr(
|
||||
ent->fts_path + fx_path_length(it->_p->d_path_abs) + 1);
|
||||
|
||||
it->entry.filename = ent->fts_name;
|
||||
it->entry.filepath = path;
|
||||
|
||||
memset(&it->entry.info, 0x0, sizeof it->entry.info);
|
||||
|
||||
it->entry.info.length = ent->fts_statp->st_size;
|
||||
|
||||
if (S_ISREG(ent->fts_statp->st_mode)) {
|
||||
it->entry.info.attrib |= FX_FILE_ATTRIB_NORMAL;
|
||||
}
|
||||
|
||||
if (S_ISDIR(ent->fts_statp->st_mode)) {
|
||||
it->entry.info.attrib |= FX_FILE_ATTRIB_DIRECTORY;
|
||||
}
|
||||
|
||||
if (S_ISBLK(ent->fts_statp->st_mode)) {
|
||||
it->entry.info.attrib |= FX_FILE_ATTRIB_BLOCK_DEVICE;
|
||||
}
|
||||
|
||||
if (S_ISCHR(ent->fts_statp->st_mode)) {
|
||||
it->entry.info.attrib |= FX_FILE_ATTRIB_CHAR_DEVICE;
|
||||
}
|
||||
|
||||
if (S_ISLNK(ent->fts_statp->st_mode)) {
|
||||
it->entry.info.attrib |= FX_FILE_ATTRIB_SYMLINK;
|
||||
}
|
||||
}
|
||||
|
||||
static void iterator_fini(fx_object *obj, void *priv)
|
||||
{
|
||||
struct fx_directory_iterator_p *it = priv;
|
||||
|
||||
if (it->entry.filepath) {
|
||||
fx_path_unref((fx_path *)it->entry.filepath);
|
||||
it->entry.filepath = NULL;
|
||||
}
|
||||
|
||||
if (it->fts) {
|
||||
fts_close(it->fts);
|
||||
}
|
||||
}
|
||||
|
||||
fx_iterator *fx_directory_begin(
|
||||
fx_directory *directory, enum fx_directory_iterator_flags flags)
|
||||
{
|
||||
fx_iterator *it_obj = fx_object_create(FX_TYPE_DIRECTORY_ITERATOR);
|
||||
struct fx_directory_iterator_p *it
|
||||
= fx_object_get_private(it_obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||
|
||||
it->flags = flags;
|
||||
it->root = directory;
|
||||
it->_p = fx_object_get_private(directory, FX_TYPE_DIRECTORY);
|
||||
|
||||
int fts_flags = FTS_COMFOLLOW | FTS_NOCHDIR;
|
||||
|
||||
const char *path_list[] = {
|
||||
fx_path_ptr(it->_p->d_path_abs),
|
||||
NULL,
|
||||
};
|
||||
|
||||
it->fts = fts_open((char *const *)path_list, fts_flags, ftsent_compare);
|
||||
|
||||
bool done = false;
|
||||
|
||||
while (!done) {
|
||||
it->ent = fts_read(it->fts);
|
||||
|
||||
if (!it->ent) {
|
||||
fx_iterator_set_status(it_obj, FX_ERR_NO_DATA);
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
if (it->ent->fts_level == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (it->ent->fts_info) {
|
||||
case FTS_DOT:
|
||||
continue;
|
||||
case FTS_F:
|
||||
done = true;
|
||||
break;
|
||||
case FTS_D:
|
||||
if (it->flags & FX_DIRECTORY_ITERATE_PARENT_LAST) {
|
||||
continue;
|
||||
}
|
||||
|
||||
done = true;
|
||||
break;
|
||||
case FTS_DP:
|
||||
if (it->flags & FX_DIRECTORY_ITERATE_PARENT_FIRST) {
|
||||
continue;
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
update_iterator_data(it);
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
static fx_iterator *iterator_begin(fx_object *obj)
|
||||
{
|
||||
return fx_directory_begin(obj, FX_DIRECTORY_ITERATE_PARENT_FIRST);
|
||||
}
|
||||
|
||||
static const fx_iterator *iterator_cbegin(const fx_object *obj)
|
||||
{
|
||||
return fx_directory_begin(
|
||||
(fx_object *)obj, FX_DIRECTORY_ITERATE_PARENT_FIRST);
|
||||
}
|
||||
|
||||
static enum fx_status iterator_move_next(const fx_iterator *obj)
|
||||
{
|
||||
struct fx_directory_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||
if (!it || !it->fts) {
|
||||
return FX_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
|
||||
while (!done) {
|
||||
it->ent = fts_read(it->fts);
|
||||
|
||||
if (!it->ent) {
|
||||
return FX_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
if (it->ent->fts_level == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (it->ent->fts_info) {
|
||||
case FTS_DOT:
|
||||
continue;
|
||||
case FTS_F:
|
||||
done = true;
|
||||
break;
|
||||
case FTS_D:
|
||||
if (it->flags & FX_DIRECTORY_ITERATE_PARENT_LAST) {
|
||||
continue;
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
case FTS_DP:
|
||||
if (it->flags & FX_DIRECTORY_ITERATE_PARENT_FIRST) {
|
||||
continue;
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
update_iterator_data(it);
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status iterator_erase(fx_iterator *obj)
|
||||
{
|
||||
struct fx_directory_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||
fx_result result = fx_directory_path_unlink(it->root, it->entry.filepath);
|
||||
if (fx_result_is_error(result)) {
|
||||
enum fx_status status = fx_error_get_status_code(result);
|
||||
fx_error_discard(result);
|
||||
return status;
|
||||
}
|
||||
|
||||
return iterator_move_next(obj);
|
||||
}
|
||||
|
||||
static fx_iterator_value iterator_get_value(fx_iterator *obj)
|
||||
{
|
||||
struct fx_directory_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||
|
||||
return FX_ITERATOR_VALUE_PTR(&it->entry);
|
||||
}
|
||||
|
||||
static const fx_iterator_value iterator_get_cvalue(const fx_iterator *obj)
|
||||
{
|
||||
struct fx_directory_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||
|
||||
return FX_ITERATOR_VALUE_CPTR(&it->entry);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
// ---- fx_directory DEFINITION
|
||||
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_directory)
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_iterable, FX_TYPE_ITERABLE)
|
||||
FX_INTERFACE_ENTRY(it_begin) = iterator_begin;
|
||||
FX_INTERFACE_ENTRY(it_cbegin) = iterator_cbegin;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_iterable, FX_TYPE_ITERABLE)
|
||||
FX_TYPE_CLASS_DEFINITION_END(fx_directory)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(fx_directory)
|
||||
FX_TYPE_ID(0x10d36546, 0x7f96, 0x464b, 0xbc4d, 0xe504b283fa45);
|
||||
FX_TYPE_CLASS(fx_directory_class);
|
||||
FX_TYPE_IMPLEMENTS(FX_TYPE_ITERABLE);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct fx_directory_p);
|
||||
FX_TYPE_INSTANCE_INIT(directory_init);
|
||||
FX_TYPE_INSTANCE_FINI(directory_fini);
|
||||
FX_TYPE_DEFINITION_END(fx_directory)
|
||||
|
||||
// ---- fx_directory_iterator DEFINITION
|
||||
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_directory_iterator)
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_iterator, FX_TYPE_ITERATOR)
|
||||
FX_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
|
||||
FX_INTERFACE_ENTRY(it_erase) = iterator_erase;
|
||||
FX_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
|
||||
FX_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR)
|
||||
FX_TYPE_CLASS_DEFINITION_END(fx_directory_iterator)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(fx_directory_iterator)
|
||||
FX_TYPE_ID(0xc707fce6, 0xc895, 0x4925, 0x8700, 0xa60641dee0cc);
|
||||
FX_TYPE_EXTENDS(FX_TYPE_ITERATOR);
|
||||
FX_TYPE_CLASS(fx_directory_iterator_class);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct fx_directory_iterator_p);
|
||||
FX_TYPE_DEFINITION_END(fx_directory_iterator)
|
||||
@@ -0,0 +1,574 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include "misc.h"
|
||||
#include "posix.h"
|
||||
|
||||
#include <fx/core/random.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/io/directory.h>
|
||||
#include <fx/io/file.h>
|
||||
#include <fx/io/path.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define CHECK_FLAG(v, f) (((v) & (f)) == (f))
|
||||
|
||||
static enum fx_status stream_close(fx_stream *);
|
||||
static enum fx_status stream_getc(fx_stream *, int *);
|
||||
static enum fx_status stream_read(fx_stream *, void *, size_t, size_t *);
|
||||
static enum fx_status stream_write(fx_stream *, const void *, size_t, size_t *);
|
||||
static enum fx_status stream_seek(fx_stream *, long long, fx_stream_seek_origin);
|
||||
static enum fx_status stream_tell(const fx_stream *, size_t *);
|
||||
|
||||
/*** PRIVATE DATA *************************************************************/
|
||||
|
||||
struct fx_file_p {
|
||||
enum fx_file_mode mode;
|
||||
int fd;
|
||||
fx_path *path;
|
||||
};
|
||||
|
||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||
|
||||
static unsigned int fx_mode_to_unix_mode(enum fx_file_mode mode)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
|
||||
if (CHECK_FLAG(mode, FX_FILE_READ_WRITE)) {
|
||||
result |= O_RDWR;
|
||||
} else if (CHECK_FLAG(mode, FX_FILE_READ_ONLY)) {
|
||||
result |= O_RDONLY;
|
||||
} else if (CHECK_FLAG(mode, FX_FILE_WRITE_ONLY)) {
|
||||
result |= O_WRONLY;
|
||||
} else {
|
||||
return (unsigned int)-1;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(mode, FX_FILE_TRUNCATE)) {
|
||||
result |= O_TRUNC;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(mode, FX_FILE_CREATE)) {
|
||||
result |= O_CREAT;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(mode, FX_FILE_CREATE_ONLY)) {
|
||||
result |= O_EXCL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static fx_result file_open_shadow(
|
||||
struct fx_file_p *original, enum fx_file_mode mode, fx_file **out)
|
||||
{
|
||||
mode |= FX_FILE_SHADOW | FX_FILE_DELETE_ON_CLOSE | FX_FILE_CREATE;
|
||||
|
||||
fx_path *dir;
|
||||
fx_path_get_directory(original->path, &dir);
|
||||
|
||||
fx_string *filename = fx_string_create();
|
||||
fx_path_get_filename(original->path, filename);
|
||||
|
||||
fx_string_prepend_cstr(filename, ".~");
|
||||
|
||||
fx_path *shadow_filename = fx_path_create_from_cstr(fx_string_get_cstr(filename));
|
||||
fx_string_unref(filename);
|
||||
|
||||
const fx_path *parts[] = {
|
||||
dir,
|
||||
shadow_filename,
|
||||
};
|
||||
|
||||
fx_path *shadow_filepath
|
||||
= fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
fx_path_unref(dir);
|
||||
fx_path_unref(shadow_filename);
|
||||
|
||||
if (fx_path_exists(shadow_filepath)) {
|
||||
fx_path_unlink(shadow_filepath);
|
||||
}
|
||||
|
||||
fx_file *shadow_file;
|
||||
fx_result status = fx_file_open(
|
||||
FX_DIRECTORY_ROOT, shadow_filepath, mode, &shadow_file);
|
||||
fx_path_unref(shadow_filepath);
|
||||
|
||||
if (fx_result_is_error(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
*out = shadow_file;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static const fx_path *file_path(const struct fx_file_p *file)
|
||||
{
|
||||
return file->path;
|
||||
}
|
||||
|
||||
static enum fx_status file_stat(struct fx_file_p *file, struct fx_file_info *out)
|
||||
{
|
||||
struct stat st;
|
||||
int err = fstat(file->fd, &st);
|
||||
|
||||
if (err != 0) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
return fx_file_info_from_stat(&st, out);
|
||||
}
|
||||
|
||||
static enum fx_status file_size(struct fx_file_p *file, size_t *out_len)
|
||||
{
|
||||
off_t cur = lseek(file->fd, 0, SEEK_CUR);
|
||||
if (cur == (off_t)-1) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
off_t len = lseek(file->fd, 0, SEEK_END);
|
||||
if (len == (off_t)-1) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
cur = lseek(file->fd, cur, SEEK_SET);
|
||||
if (cur == (off_t)-1) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
*out_len = (size_t)len;
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status file_cursor(struct fx_file_p *file, size_t *out_pos)
|
||||
{
|
||||
off_t cur = lseek(file->fd, 0, SEEK_CUR);
|
||||
if (cur == (off_t)-1) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
*out_pos = (size_t)cur;
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status file_resize(struct fx_file_p *file, size_t len)
|
||||
{
|
||||
int err = ftruncate(file->fd, len);
|
||||
if (err == 0) {
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
static enum fx_status file_seek(
|
||||
struct fx_file_p *file, long long offset, enum fx_seek_basis basis)
|
||||
{
|
||||
int whence;
|
||||
switch (basis) {
|
||||
case FX_SEEK_BEGINNING:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case FX_SEEK_CURRENT:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case FX_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
return FX_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
int err = lseek(file->fd, offset, whence);
|
||||
if (err == (off_t)-1) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status file_swap_shadow(
|
||||
struct fx_file_p *main_file, struct fx_file_p *shadow_file)
|
||||
{
|
||||
if (main_file->mode & FX_FILE_SHADOW) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!(shadow_file->mode & FX_FILE_SHADOW)) {
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
fx_path *dir_path;
|
||||
fx_path_get_directory(main_file->path, &dir_path);
|
||||
|
||||
fx_path *tmp_path = NULL;
|
||||
|
||||
while (1) {
|
||||
char tmp_name[16];
|
||||
z__fx_io_generate_tmp_filename(tmp_name, sizeof tmp_name);
|
||||
fx_path *tmp_name_p = fx_path_create_from_cstr(tmp_name);
|
||||
|
||||
const fx_path *parts[] = {
|
||||
dir_path,
|
||||
tmp_name_p,
|
||||
};
|
||||
|
||||
tmp_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
|
||||
fx_path_unref(tmp_name_p);
|
||||
|
||||
if (!fx_path_exists(tmp_path)) {
|
||||
break;
|
||||
}
|
||||
|
||||
fx_path_unref(tmp_path);
|
||||
tmp_path = NULL;
|
||||
}
|
||||
|
||||
fx_path_unref(dir_path);
|
||||
|
||||
int err;
|
||||
|
||||
err = rename(fx_path_ptr(main_file->path), fx_path_ptr(tmp_path));
|
||||
err = rename(fx_path_ptr(shadow_file->path), fx_path_ptr(main_file->path));
|
||||
err = rename(fx_path_ptr(tmp_path), fx_path_ptr(shadow_file->path));
|
||||
|
||||
fx_path_unref(tmp_path);
|
||||
|
||||
int fd = main_file->fd;
|
||||
main_file->fd = shadow_file->fd;
|
||||
shadow_file->fd = fd;
|
||||
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status file_read(
|
||||
struct fx_file_p *file, size_t offset, size_t len, void *buf, size_t *nr_read)
|
||||
{
|
||||
if (offset != FX_OFFSET_CURRENT) {
|
||||
lseek(file->fd, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
long r = read(file->fd, buf, len);
|
||||
|
||||
enum fx_status status = FX_SUCCESS;
|
||||
|
||||
if (r < 0) {
|
||||
status = fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
*nr_read = r;
|
||||
return status;
|
||||
}
|
||||
|
||||
static enum fx_status file_write(
|
||||
struct fx_file_p *file, size_t offset, size_t len, const void *buf,
|
||||
size_t *nr_written)
|
||||
{
|
||||
if (offset != FX_OFFSET_CURRENT) {
|
||||
lseek(file->fd, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
long w = write(file->fd, buf, len);
|
||||
|
||||
enum fx_status status = FX_SUCCESS;
|
||||
|
||||
if (w < 0) {
|
||||
status = fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
*nr_written = w;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*** STREAM FUNCTIONS *********************************************************/
|
||||
|
||||
static enum fx_status stream_close(fx_stream *stream)
|
||||
{
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status stream_getc(fx_stream *stream, int *out)
|
||||
{
|
||||
struct fx_file_p *file = fx_object_get_private(stream, FX_TYPE_FILE);
|
||||
char c;
|
||||
size_t nr_read = 0;
|
||||
|
||||
enum fx_status status
|
||||
= file_read(file, FX_OFFSET_CURRENT, sizeof c, &c, &nr_read);
|
||||
if (status != FX_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (nr_read == 0) {
|
||||
return FX_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
*out = c;
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status stream_read(
|
||||
fx_stream *stream, void *buf, size_t max, size_t *nr_read)
|
||||
{
|
||||
struct fx_file_p *file = fx_object_get_private(stream, FX_TYPE_FILE);
|
||||
|
||||
enum fx_status status
|
||||
= file_read(file, FX_OFFSET_CURRENT, max, buf, 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_file_p *file = fx_object_get_private(stream, FX_TYPE_FILE);
|
||||
|
||||
enum fx_status status
|
||||
= file_write(file, FX_OFFSET_CURRENT, count, buf, nr_written);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static enum fx_status stream_seek(
|
||||
fx_stream *stream, long long offset, fx_stream_seek_origin origin)
|
||||
{
|
||||
fx_seek_basis basis;
|
||||
switch (origin) {
|
||||
case FX_STREAM_SEEK_START:
|
||||
basis = FX_SEEK_BEGINNING;
|
||||
break;
|
||||
case FX_STREAM_SEEK_CURRENT:
|
||||
basis = FX_SEEK_CURRENT;
|
||||
break;
|
||||
case FX_STREAM_SEEK_END:
|
||||
basis = FX_SEEK_END;
|
||||
break;
|
||||
default:
|
||||
return FX_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
struct fx_file_p *file = fx_object_get_private(stream, FX_TYPE_FILE);
|
||||
|
||||
return file_seek(file, offset, basis);
|
||||
}
|
||||
|
||||
static enum fx_status stream_tell(const fx_stream *stream, size_t *pos)
|
||||
{
|
||||
const struct fx_file_p *file = fx_object_get_private(stream, FX_TYPE_FILE);
|
||||
off_t v = lseek(file->fd, 0, SEEK_CUR);
|
||||
if (v == (off_t)-1) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
*pos = v;
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
fx_result fx_file_open(
|
||||
fx_directory *root, const fx_path *path, enum fx_file_mode mode, fx_file **out)
|
||||
{
|
||||
const fx_path *file_path = path;
|
||||
unsigned int flags = fx_mode_to_unix_mode(mode);
|
||||
|
||||
if (flags == (unsigned int)-1) {
|
||||
return FX_RESULT_ERR(INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
const fx_path *root_path = NULL;
|
||||
bool free_root_path = false;
|
||||
if (root) {
|
||||
root_path = fx_directory_get_path(root);
|
||||
} else {
|
||||
root_path = fx_path_create_cwd();
|
||||
free_root_path = true;
|
||||
}
|
||||
|
||||
const fx_path *parts[] = {
|
||||
root_path,
|
||||
file_path,
|
||||
};
|
||||
|
||||
fx_path *abs_path = fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||
|
||||
if (free_root_path) {
|
||||
fx_path_unref((fx_path *)root_path);
|
||||
}
|
||||
|
||||
if (!abs_path) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
int fd = open(fx_path_ptr(abs_path), flags, 0644);
|
||||
if (fd == -1) {
|
||||
fx_path_unref(abs_path);
|
||||
return FX_RESULT_STATUS(
|
||||
fx_status_from_errno(errno, FX_ERR_IO_FAILURE));
|
||||
}
|
||||
|
||||
fx_file *file = fx_object_create(FX_TYPE_FILE);
|
||||
if (!file) {
|
||||
close(fd);
|
||||
fx_path_unref(abs_path);
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
struct fx_file_p *p = fx_object_get_private(file, FX_TYPE_FILE);
|
||||
fx_stream_cfg *cfg = fx_object_get_protected(file, FX_TYPE_STREAM);
|
||||
|
||||
if (mode & FX_FILE_READ_ONLY) {
|
||||
cfg->s_mode |= FX_STREAM_READ;
|
||||
}
|
||||
|
||||
if (mode & FX_FILE_WRITE_ONLY) {
|
||||
cfg->s_mode |= FX_STREAM_WRITE;
|
||||
}
|
||||
|
||||
if (mode & FX_FILE_BINARY) {
|
||||
cfg->s_mode |= FX_STREAM_BINARY;
|
||||
}
|
||||
|
||||
p->fd = fd;
|
||||
p->path = abs_path;
|
||||
p->mode = mode;
|
||||
|
||||
*out = file;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
fx_result fx_file_open_temp(enum fx_file_mode mode, fx_file **out)
|
||||
{
|
||||
mode |= FX_FILE_DELETE_ON_CLOSE;
|
||||
|
||||
char name[16];
|
||||
char path[128];
|
||||
|
||||
while (1) {
|
||||
z__fx_io_generate_tmp_filename(name, sizeof name);
|
||||
snprintf(path, sizeof path, "/tmp/%s", name);
|
||||
fx_path *rpath = fx_path_create_from_cstr(path);
|
||||
|
||||
fx_result status = fx_file_open(
|
||||
FX_DIRECTORY_ROOT, rpath, mode | FX_FILE_CREATE_ONLY, out);
|
||||
|
||||
if (fx_error_get_status_code(status) == FX_ERR_NAME_EXISTS) {
|
||||
fx_path_unref(rpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
fx_path_unlink(rpath);
|
||||
fx_path_unref(rpath);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
fx_result fx_file_open_shadow(fx_file *original, enum fx_file_mode mode, fx_file **out)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_FILE, file_open_shadow, original, mode, out);
|
||||
}
|
||||
|
||||
const fx_path *fx_file_path(const fx_file *file)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_FILE, file_path, file);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_stat(fx_file *file, struct fx_file_info *out)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_FILE, file_stat, file, out);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_size(fx_file *file, size_t *out_len)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_FILE, file_size, file, out_len);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_cursor(fx_file *file, size_t *out_pos)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_FILE, file_cursor, file, out_pos);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_resize(fx_file *file, size_t len)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_FILE, file_resize, file, len);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_seek(fx_file *file, long long offset, enum fx_seek_basis basis)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_FILE, file_seek, file, offset, basis);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_swap_shadow(fx_file *main_file, fx_file *shadow_file)
|
||||
{
|
||||
struct fx_file_p *main_p = fx_object_get_private(main_file, FX_TYPE_FILE);
|
||||
struct fx_file_p *shadow_p = fx_object_get_private(main_file, FX_TYPE_FILE);
|
||||
return file_swap_shadow(main_p, shadow_p);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_read(
|
||||
fx_file *file, size_t offset, size_t len, void *buf, size_t *nr_read)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_FILE, file_read, file, offset, len, buf, nr_read);
|
||||
}
|
||||
|
||||
enum fx_status fx_file_write(
|
||||
fx_file *file, size_t offset, size_t len, const void *buf, size_t *nr_written)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(
|
||||
FX_TYPE_FILE, file_write, file, offset, len, buf, nr_written);
|
||||
}
|
||||
|
||||
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||
|
||||
static void file_init(fx_object *obj, void *priv)
|
||||
{
|
||||
struct fx_file_p *file = priv;
|
||||
}
|
||||
|
||||
static void file_fini(fx_object *obj, void *priv)
|
||||
{
|
||||
struct fx_file_p *file = priv;
|
||||
close(file->fd);
|
||||
|
||||
if (file->mode & FX_FILE_DELETE_ON_CLOSE) {
|
||||
fx_path_unlink(file->path);
|
||||
}
|
||||
|
||||
fx_path_unref(file->path);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_file)
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_stream, FX_TYPE_STREAM)
|
||||
FX_INTERFACE_ENTRY(s_close) = stream_close;
|
||||
FX_INTERFACE_ENTRY(s_getc) = stream_getc;
|
||||
FX_INTERFACE_ENTRY(s_read) = stream_read;
|
||||
FX_INTERFACE_ENTRY(s_write) = stream_write;
|
||||
FX_INTERFACE_ENTRY(s_seek) = stream_seek;
|
||||
FX_INTERFACE_ENTRY(s_tell) = stream_tell;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_stream, FX_TYPE_STREAM)
|
||||
FX_TYPE_CLASS_DEFINITION_END(fx_file)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(fx_file)
|
||||
FX_TYPE_ID(0x495a73f6, 0xb8c3, 0x4e17, 0xb5f4, 0x6fc321f67c7b);
|
||||
FX_TYPE_EXTENDS(FX_TYPE_STREAM);
|
||||
FX_TYPE_CLASS(fx_file_class);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct fx_file_p);
|
||||
FX_TYPE_INSTANCE_INIT(file_init);
|
||||
FX_TYPE_INSTANCE_FINI(file_fini);
|
||||
FX_TYPE_DEFINITION_END(fx_file)
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "misc.h"
|
||||
|
||||
#include <fx/core/random.h>
|
||||
|
||||
void z__fx_io_generate_tmp_filename(char *out, size_t len)
|
||||
{
|
||||
static const char *alphabet
|
||||
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
"01234567"
|
||||
"89+=-_.";
|
||||
static const size_t alphabet_len = 67;
|
||||
|
||||
fx_random_ctx *ctx = fx_random_global_ctx();
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
int v = fx_random_next_int64(ctx) % alphabet_len;
|
||||
out[i] = alphabet[v];
|
||||
}
|
||||
|
||||
out[len - 1] = 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef _IO_DARWIN_MISC_H_
|
||||
#define _IO_DARWIN_MISC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
extern void z__fx_io_generate_tmp_filename(char *out, size_t len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,399 @@
|
||||
#include "posix.h"
|
||||
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/io/file.h>
|
||||
#include <fx/io/path.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*** PRIVATE DATA *************************************************************/
|
||||
|
||||
struct fx_path_p {
|
||||
fx_string *p_pathstr;
|
||||
};
|
||||
|
||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||
|
||||
static fx_path *path_make_absolute(const struct fx_path_p *in)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static fx_path *path_make_relative(const struct fx_path_p *in)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static fx_path *path_make_canonical(const struct fx_path_p *in)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool path_is_absolute(const struct fx_path_p *path)
|
||||
{
|
||||
const char *s = fx_string_get_cstr(path->p_pathstr);
|
||||
return s[0] == '/';
|
||||
}
|
||||
|
||||
static const char *path_ptr(const struct fx_path_p *path)
|
||||
{
|
||||
return fx_string_get_cstr(path->p_pathstr);
|
||||
}
|
||||
|
||||
static enum fx_status path_stat(const struct fx_path_p *path, struct fx_file_info *out)
|
||||
{
|
||||
struct stat st;
|
||||
int err = stat(path_ptr(path), &st);
|
||||
|
||||
if (err != 0) {
|
||||
return fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
return fx_file_info_from_stat(&st, out);
|
||||
}
|
||||
|
||||
static bool path_exists(const struct fx_path_p *path)
|
||||
{
|
||||
fx_file_info info;
|
||||
if (!FX_OK(path_stat(path, &info))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool path_is_file(const struct fx_path_p *path)
|
||||
{
|
||||
fx_file_info info;
|
||||
if (!FX_OK(path_stat(path, &info))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (info.attrib & FX_FILE_ATTRIB_NORMAL) != 0;
|
||||
}
|
||||
|
||||
static bool path_is_directory(const struct fx_path_p *path)
|
||||
{
|
||||
fx_file_info info;
|
||||
if (!FX_OK(path_stat(path, &info))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (info.attrib & FX_FILE_ATTRIB_DIRECTORY) != 0;
|
||||
}
|
||||
|
||||
static void append_path(struct fx_path_p *dest, const struct fx_path_p *src)
|
||||
{
|
||||
if (path_is_absolute(src)) {
|
||||
fx_string_clear(dest->p_pathstr);
|
||||
fx_string_append_s(dest->p_pathstr, src->p_pathstr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fx_string_get_size(dest->p_pathstr, FX_STRLEN_NORMAL) > 0
|
||||
&& fx_string_get_last_char(dest->p_pathstr) != '/'
|
||||
&& fx_string_get_first_char(src->p_pathstr) != '/') {
|
||||
char s[] = {'/', 0};
|
||||
fx_string_append_cstr(dest->p_pathstr, s);
|
||||
}
|
||||
|
||||
fx_string_append_s(dest->p_pathstr, src->p_pathstr);
|
||||
}
|
||||
|
||||
static enum fx_status path_unlink(const struct fx_path_p *path)
|
||||
{
|
||||
int err = remove(fx_string_get_cstr(path->p_pathstr));
|
||||
return err == 0 ? FX_SUCCESS : fx_status_from_errno(errno, FX_ERR_IO_FAILURE);
|
||||
}
|
||||
|
||||
static enum fx_status path_get_directory(
|
||||
const struct fx_path_p *path, fx_path **out_dir_path)
|
||||
{
|
||||
fx_string *path_str = path->p_pathstr;
|
||||
long len = fx_string_get_size(path_str, FX_STRLEN_NORMAL);
|
||||
|
||||
const char *path_cstr = fx_string_get_cstr(path_str);
|
||||
char *sep = strrchr(path_cstr, '/');
|
||||
|
||||
if (!sep) {
|
||||
*out_dir_path = fx_path_create();
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
size_t dir_path_len = (size_t)(sep - path_cstr);
|
||||
fx_string *dir_path_s = fx_string_get_substr(path_str, 0, dir_path_len);
|
||||
|
||||
fx_path *dir_path = fx_path_create_from_cstr(fx_string_get_cstr(dir_path_s));
|
||||
fx_string_unref(dir_path_s);
|
||||
|
||||
*out_dir_path = dir_path;
|
||||
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static enum fx_status path_get_filename(
|
||||
const struct fx_path_p *path, fx_string *out_name)
|
||||
{
|
||||
fx_string *path_str = path->p_pathstr;
|
||||
long len = fx_string_get_size(path_str, FX_STRLEN_NORMAL);
|
||||
|
||||
char *sep = strrchr(fx_string_get_cstr(path_str), '/');
|
||||
|
||||
if (!sep) {
|
||||
fx_string_append_s(out_name, path_str);
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
const char *filename = sep;
|
||||
while (*filename == '/' && *filename != '\0') {
|
||||
filename++;
|
||||
}
|
||||
|
||||
if (*filename == '\0') {
|
||||
fx_string_clear(out_name);
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
fx_string_append_cstr(out_name, filename);
|
||||
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static size_t path_length(const struct fx_path_p *path)
|
||||
{
|
||||
return fx_string_get_size(path->p_pathstr, FX_STRLEN_NORMAL);
|
||||
}
|
||||
|
||||
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
fx_path *fx_path_create_root()
|
||||
{
|
||||
const char *system_drive = "/";
|
||||
size_t system_drive_len = strlen(system_drive);
|
||||
|
||||
fx_path *path = fx_path_create();
|
||||
if (!path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct fx_path_p *p = fx_object_get_private(path, FX_TYPE_PATH);
|
||||
|
||||
fx_string_append_cstr(p->p_pathstr, system_drive);
|
||||
if (system_drive[system_drive_len - 1] != '\\') {
|
||||
fx_string_append_c(p->p_pathstr, '\\');
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
fx_path *fx_path_create_cwd()
|
||||
{
|
||||
const long buf_len = 2048;
|
||||
char *buf = malloc(buf_len);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!getcwd(buf, buf_len)) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fx_path *path = fx_path_create();
|
||||
if (!path) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct fx_path_p *p = fx_object_get_private(path, FX_TYPE_PATH);
|
||||
|
||||
fx_string_append_cstr(p->p_pathstr, buf);
|
||||
free(buf);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
fx_path *fx_path_create_from_cstr(const char *cstr)
|
||||
{
|
||||
fx_path *path = fx_path_create();
|
||||
if (!path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct fx_path_p *p = fx_object_get_private(path, FX_TYPE_PATH);
|
||||
|
||||
char prev = 0;
|
||||
|
||||
for (size_t i = 0; cstr[i]; i++) {
|
||||
char c = cstr[i];
|
||||
if (c == '\\') {
|
||||
c = '/';
|
||||
}
|
||||
|
||||
if (prev == '/' && c == '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
fx_string_append_c(p->p_pathstr, c);
|
||||
prev = c;
|
||||
}
|
||||
|
||||
while (fx_string_get_last_char(p->p_pathstr) == '/') {
|
||||
fx_string_pop_back(p->p_pathstr);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
fx_path *fx_path_duplicate(const fx_path *path)
|
||||
{
|
||||
fx_path *new_path = fx_path_create();
|
||||
if (!path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct fx_path_p *old_p = fx_object_get_private(path, FX_TYPE_PATH);
|
||||
struct fx_path_p *new_p = fx_object_get_private(new_path, FX_TYPE_PATH);
|
||||
|
||||
new_p->p_pathstr = fx_string_duplicate(old_p->p_pathstr);
|
||||
if (!new_p->p_pathstr) {
|
||||
fx_path_unref(new_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new_path;
|
||||
}
|
||||
|
||||
fx_path *fx_path_join(const fx_path *paths[], size_t nr_paths)
|
||||
{
|
||||
fx_path *result = fx_path_create();
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct fx_path_p *result_p = fx_object_get_private(result, FX_TYPE_PATH);
|
||||
|
||||
for (size_t i = 0; i < nr_paths; i++) {
|
||||
if (paths[i]) {
|
||||
struct fx_path_p *path_p
|
||||
= fx_object_get_private(paths[i], FX_TYPE_PATH);
|
||||
append_path(result_p, path_p);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fx_path *fx_path_make_absolute(const fx_path *in)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_make_absolute, in);
|
||||
}
|
||||
|
||||
fx_path *fx_path_make_relative(const fx_path *in)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_make_relative, in);
|
||||
}
|
||||
|
||||
fx_path *fx_path_make_canonical(const fx_path *in)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_make_canonical, in);
|
||||
}
|
||||
|
||||
bool fx_path_is_absolute(const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_is_absolute, path);
|
||||
}
|
||||
|
||||
bool fx_path_exists(const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_exists, path);
|
||||
}
|
||||
|
||||
bool fx_path_is_file(const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_is_file, path);
|
||||
}
|
||||
|
||||
bool fx_path_is_directory(const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_is_directory, path);
|
||||
}
|
||||
|
||||
enum fx_status fx_path_stat(const fx_path *path, struct fx_file_info *out)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_PATH, path_stat, path, out);
|
||||
}
|
||||
|
||||
enum fx_status fx_path_unlink(const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_unlink, path);
|
||||
}
|
||||
|
||||
enum fx_status fx_path_get_directory(const fx_path *path, fx_path **out_dir_path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_PATH, path_get_directory, path, out_dir_path);
|
||||
}
|
||||
|
||||
enum fx_status fx_path_get_filename(const fx_path *path, fx_string *out_name)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC(FX_TYPE_PATH, path_get_filename, path, out_name);
|
||||
}
|
||||
|
||||
const char *fx_path_ptr(const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_ptr, path);
|
||||
}
|
||||
|
||||
size_t fx_path_length(const fx_path *path)
|
||||
{
|
||||
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_PATH, path_length, path);
|
||||
}
|
||||
|
||||
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||
|
||||
static void path_init(fx_object *obj, void *priv)
|
||||
{
|
||||
struct fx_path_p *path = priv;
|
||||
|
||||
path->p_pathstr = fx_string_create();
|
||||
if (!path->p_pathstr) {
|
||||
/* TODO return error */
|
||||
}
|
||||
}
|
||||
|
||||
void path_fini(fx_object *obj, void *priv)
|
||||
{
|
||||
struct fx_path_p *path = priv;
|
||||
|
||||
fx_string_unref(path->p_pathstr);
|
||||
}
|
||||
|
||||
void path_to_string(const fx_object *obj, fx_stream *out)
|
||||
{
|
||||
struct fx_path_p *path = fx_object_get_private(obj, FX_TYPE_PATH);
|
||||
|
||||
fx_stream_write_cstr(out, fx_string_get_cstr(path->p_pathstr), NULL);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_path)
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = path_to_string;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
FX_TYPE_CLASS_DEFINITION_END(fx_path)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(fx_path)
|
||||
FX_TYPE_ID(0x56dc32eb, 0xea96, 0x46ed, 0x85d3, 0x760fa4ad61f4);
|
||||
FX_TYPE_CLASS(fx_path_class);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct fx_path_p);
|
||||
FX_TYPE_INSTANCE_INIT(path_init);
|
||||
FX_TYPE_INSTANCE_FINI(path_fini);
|
||||
FX_TYPE_DEFINITION_END(fx_path)
|
||||
@@ -0,0 +1,131 @@
|
||||
#include <fx/core/error.h>
|
||||
#include <fx/core/status.h>
|
||||
#include <fx/io/file.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
enum fx_status fx_status_from_errno(int error, enum fx_status default_value)
|
||||
{
|
||||
switch (error) {
|
||||
case 0:
|
||||
return FX_SUCCESS;
|
||||
case ENOENT:
|
||||
return FX_ERR_NO_ENTRY;
|
||||
case EEXIST:
|
||||
return FX_ERR_NAME_EXISTS;
|
||||
case ENOMEM:
|
||||
return FX_ERR_NO_MEMORY;
|
||||
case EINVAL:
|
||||
return FX_ERR_INVALID_ARGUMENT;
|
||||
case EIO:
|
||||
return FX_ERR_IO_FAILURE;
|
||||
case EISDIR:
|
||||
return FX_ERR_IS_DIRECTORY;
|
||||
case ENOTDIR:
|
||||
return FX_ERR_NOT_DIRECTORY;
|
||||
case EPERM:
|
||||
case EACCES:
|
||||
return FX_ERR_PERMISSION_DENIED;
|
||||
case ENOTSUP:
|
||||
case ENOSYS:
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
default:
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
fx_result fx_result_from_errno_with_filepath(
|
||||
int error, const char *path, enum fx_status default_value)
|
||||
{
|
||||
switch (error) {
|
||||
case 0:
|
||||
return FX_RESULT_SUCCESS;
|
||||
case ENOENT:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_NO_ENTRY, "Path @i{%s} does not exist", path);
|
||||
case ENOTDIR:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_NOT_DIRECTORY, "Path @i{%s} is not a directory",
|
||||
path);
|
||||
case EISDIR:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_IS_DIRECTORY, "Path @i{%s} is a directory", path);
|
||||
case EPERM:
|
||||
case EACCES:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_PERMISSION_DENIED,
|
||||
"Permission denied while accessing path @i{%s}", path);
|
||||
default:
|
||||
return FX_RESULT_STATUS(fx_status_from_errno(error, default_value));
|
||||
}
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
fx_result fx_result_from_errno_with_subfilepath(
|
||||
int error, const char *path, const char *dir_path,
|
||||
enum fx_status default_value)
|
||||
{
|
||||
if (!dir_path) {
|
||||
return fx_result_propagate(fx_result_from_errno_with_filepath(
|
||||
error, path, default_value));
|
||||
}
|
||||
|
||||
switch (error) {
|
||||
case 0:
|
||||
return FX_RESULT_SUCCESS;
|
||||
case ENOENT:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_NO_ENTRY,
|
||||
"Path @i{%s} in directory @i{%s} does not exist", path,
|
||||
dir_path);
|
||||
case ENOTDIR:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_NOT_DIRECTORY,
|
||||
"Path @i{%s} in directory @i{%s} is not a directory",
|
||||
path, dir_path);
|
||||
case EISDIR:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_IS_DIRECTORY,
|
||||
"Path @i{%s} in directory @i{%s} is a directory", path,
|
||||
dir_path);
|
||||
case EPERM:
|
||||
case EACCES:
|
||||
return FX_RESULT_STATUS_WITH_STRING(
|
||||
FX_ERR_PERMISSION_DENIED,
|
||||
"Permission denied while accessing path @i{%s} in "
|
||||
"directory @i{%s}",
|
||||
path, dir_path);
|
||||
default:
|
||||
return FX_RESULT_STATUS(fx_status_from_errno(error, default_value));
|
||||
}
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
enum fx_status fx_file_info_from_stat(const struct stat *st, struct fx_file_info *out)
|
||||
{
|
||||
out->length = st->st_size;
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
out->attrib |= FX_FILE_ATTRIB_NORMAL;
|
||||
}
|
||||
|
||||
if (S_ISDIR(st->st_mode)) {
|
||||
out->attrib |= FX_FILE_ATTRIB_DIRECTORY;
|
||||
}
|
||||
|
||||
if (S_ISBLK(st->st_mode)) {
|
||||
out->attrib |= FX_FILE_ATTRIB_BLOCK_DEVICE;
|
||||
}
|
||||
|
||||
if (S_ISCHR(st->st_mode)) {
|
||||
out->attrib |= FX_FILE_ATTRIB_CHAR_DEVICE;
|
||||
}
|
||||
|
||||
if (S_ISLNK(st->st_mode)) {
|
||||
out->attrib |= FX_FILE_ATTRIB_SYMLINK;
|
||||
}
|
||||
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef _IO_DARWIN_POSIX_H_
|
||||
#define _IO_DARWIN_POSIX_H_
|
||||
|
||||
#include <fx/core/error.h>
|
||||
#include <fx/core/status.h>
|
||||
|
||||
struct stat;
|
||||
struct fx_file_info;
|
||||
|
||||
extern enum fx_status fx_status_from_errno(int error, enum fx_status default_value);
|
||||
extern fx_result fx_result_from_errno_with_filepath(
|
||||
int error, const char *path, enum fx_status default_value);
|
||||
extern fx_result fx_result_from_errno_with_subfilepath(
|
||||
int error, const char *path, const char *dir_path,
|
||||
enum fx_status default_value);
|
||||
extern enum fx_status fx_file_info_from_stat(
|
||||
const struct stat *in, struct fx_file_info *out);
|
||||
|
||||
#endif
|
||||
@@ -123,7 +123,7 @@ struct fx_path *fx_path_create_from_cstr(const char *cstr)
|
||||
prev = c;
|
||||
}
|
||||
|
||||
while (fx_string_back(path->pathstr) == '/') {
|
||||
while (fx_string_get_last_char(path->pathstr) == '/') {
|
||||
fx_string_pop_back(path->pathstr);
|
||||
}
|
||||
|
||||
@@ -138,8 +138,8 @@ static void append_path(struct fx_path *dest, const struct fx_path *src)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fx_string_back(dest->pathstr) != '/'
|
||||
&& fx_string_front(src->pathstr) != '/') {
|
||||
if (fx_string_get_last_char(dest->pathstr) != '/'
|
||||
&& fx_string_get_first_char(src->pathstr) != '/') {
|
||||
char s[] = {'/', 0};
|
||||
fx_string_append_cstr(dest->pathstr, s);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ struct fx_path *fx_path_make_canonical(const struct fx_path *in)
|
||||
|
||||
bool fx_path_is_absolute(const struct fx_path *path)
|
||||
{
|
||||
const char *s = fx_string_ptr(path->pathstr);
|
||||
const char *s = fx_string_get_cstr(path->pathstr);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; s[i]; i++) {
|
||||
@@ -231,7 +231,7 @@ bool fx_path_is_directory(const struct fx_path *path)
|
||||
|
||||
const char *fx_path_ptr(const struct fx_path *path)
|
||||
{
|
||||
return fx_string_ptr(path->pathstr);
|
||||
return fx_string_get_cstr(path->pathstr);
|
||||
}
|
||||
|
||||
void path_release(struct fx_dsref* obj)
|
||||
@@ -244,5 +244,5 @@ void path_to_string(struct fx_dsref* obj, struct fx_stringstream* out)
|
||||
{
|
||||
struct fx_path *path = (struct fx_path *)obj;
|
||||
|
||||
fx_stringstream_add(out, fx_string_ptr(path->pathstr));
|
||||
fx_stringstream_add(out, fx_string_get_cstr(path->pathstr));
|
||||
}
|
||||
+10
-6
@@ -3,18 +3,22 @@
|
||||
|
||||
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||
|
||||
static enum fx_status bitcode_serialise(
|
||||
fx_serial_ctx *serial, fx_object *src, fx_stream *dest,
|
||||
static struct fx_error *bitcode_serialise(
|
||||
fx_serial_ctx *serial,
|
||||
fx_object *src,
|
||||
fx_stream *dest,
|
||||
enum fx_serial_flags flags)
|
||||
{
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
return FX_RESULT_ERR(NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
static enum fx_status bitcode_deserialise(
|
||||
fx_serial_ctx *serial, fx_stream *src, fx_object **dest,
|
||||
static struct fx_error *bitcode_deserialise(
|
||||
fx_serial_ctx *serial,
|
||||
fx_stream *src,
|
||||
fx_object **dest,
|
||||
enum fx_serial_flags flags)
|
||||
{
|
||||
return FX_ERR_NOT_SUPPORTED;
|
||||
return FX_RESULT_ERR(NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
static void bitcode_serial_ctx_init(fx_object *obj, void *priv)
|
||||
|
||||
+30
-10
@@ -10,14 +10,16 @@
|
||||
|
||||
static void serial_ctx_init(fx_object *obj, void *priv)
|
||||
{
|
||||
fx_serial_ctx_data *data = fx_object_get_protected(obj, FX_TYPE_SERIAL_CTX);
|
||||
fx_serial_ctx_data *data
|
||||
= fx_object_get_protected(obj, FX_TYPE_SERIAL_CTX);
|
||||
|
||||
data->ctx_streambuf = fx_stream_buffer_create_dynamic(2048);
|
||||
}
|
||||
|
||||
static void serial_ctx_fini(fx_object *obj, void *priv)
|
||||
{
|
||||
fx_serial_ctx_data *data = fx_object_get_protected(obj, FX_TYPE_SERIAL_CTX);
|
||||
fx_serial_ctx_data *data
|
||||
= fx_object_get_protected(obj, FX_TYPE_SERIAL_CTX);
|
||||
|
||||
fx_stream_buffer_unref(data->ctx_streambuf);
|
||||
}
|
||||
@@ -40,18 +42,36 @@ FX_TYPE_DEFINITION_END(fx_serial_ctx)
|
||||
|
||||
/*** ITERATOR FUNCTIONS *******************************************************/
|
||||
|
||||
enum fx_status fx_serial_ctx_serialise(
|
||||
fx_serial_ctx *ctx, fx_object *src, fx_stream *dest, enum fx_serial_flags flags)
|
||||
fx_result fx_serial_ctx_serialise(
|
||||
fx_serial_ctx *ctx,
|
||||
fx_object *src,
|
||||
fx_stream *dest,
|
||||
enum fx_serial_flags flags)
|
||||
{
|
||||
FX_CLASS_DISPATCH_VIRTUAL(
|
||||
fx_serial_ctx, FX_TYPE_SERIAL_CTX, FX_ERR_NOT_SUPPORTED,
|
||||
s_serialise, ctx, src, dest, flags);
|
||||
fx_serial_ctx,
|
||||
FX_TYPE_SERIAL_CTX,
|
||||
FX_RESULT_ERR(NOT_SUPPORTED),
|
||||
s_serialise,
|
||||
ctx,
|
||||
src,
|
||||
dest,
|
||||
flags);
|
||||
}
|
||||
|
||||
enum fx_status fx_serial_ctx_deserialise(
|
||||
fx_serial_ctx *ctx, fx_stream *src, fx_object **dest, enum fx_serial_flags flags)
|
||||
fx_result fx_serial_ctx_deserialise(
|
||||
fx_serial_ctx *ctx,
|
||||
fx_stream *src,
|
||||
fx_object **dest,
|
||||
enum fx_serial_flags flags)
|
||||
{
|
||||
FX_CLASS_DISPATCH_VIRTUAL(
|
||||
fx_serial_ctx, FX_TYPE_SERIAL_CTX, FX_ERR_NOT_SUPPORTED,
|
||||
s_deserialise, ctx, src, dest, flags);
|
||||
fx_serial_ctx,
|
||||
FX_TYPE_SERIAL_CTX,
|
||||
FX_RESULT_ERR(NOT_SUPPORTED),
|
||||
s_deserialise,
|
||||
ctx,
|
||||
src,
|
||||
dest,
|
||||
flags);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,16 @@ typedef enum fx_serial_flags {
|
||||
FX_DECLARE_TYPE(fx_serial_ctx);
|
||||
|
||||
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_serial_ctx)
|
||||
fx_status (*s_serialise)(
|
||||
fx_serial_ctx *, fx_object *, fx_stream *, fx_serial_flags);
|
||||
fx_status (*s_deserialise)(
|
||||
fx_serial_ctx *, fx_stream *, fx_object **, fx_serial_flags);
|
||||
fx_result (*s_serialise)(
|
||||
fx_serial_ctx *,
|
||||
fx_object *,
|
||||
fx_stream *,
|
||||
fx_serial_flags);
|
||||
fx_result (*s_deserialise)(
|
||||
fx_serial_ctx *,
|
||||
fx_stream *,
|
||||
fx_object **,
|
||||
fx_serial_flags);
|
||||
FX_TYPE_CLASS_DECLARATION_END(fx_serial_ctx)
|
||||
|
||||
typedef struct fx_serial_ctx_data {
|
||||
@@ -31,11 +37,17 @@ typedef struct fx_serial_ctx_data {
|
||||
|
||||
FX_API fx_type fx_serial_ctx_get_type(void);
|
||||
|
||||
FX_API fx_status fx_serial_ctx_serialise(
|
||||
fx_serial_ctx *ctx, fx_object *src, fx_stream *dest, fx_serial_flags flags);
|
||||
FX_API fx_result fx_serial_ctx_serialise(
|
||||
fx_serial_ctx *ctx,
|
||||
fx_object *src,
|
||||
fx_stream *dest,
|
||||
fx_serial_flags flags);
|
||||
|
||||
FX_API fx_status fx_serial_ctx_deserialise(
|
||||
fx_serial_ctx *ctx, fx_stream *src, fx_object **dest, fx_serial_flags flags);
|
||||
FX_API fx_result fx_serial_ctx_deserialise(
|
||||
fx_serial_ctx *ctx,
|
||||
fx_stream *src,
|
||||
fx_object **dest,
|
||||
fx_serial_flags flags);
|
||||
|
||||
FX_DECLS_END;
|
||||
|
||||
|
||||
+221
-180
File diff suppressed because it is too large
Load Diff
+8
-4
@@ -19,18 +19,18 @@ static void get_error_id(
|
||||
fx_stringstream *id = fx_stringstream_create_with_buffer(out, max);
|
||||
|
||||
if (vendor_name) {
|
||||
fx_stream_write_string(id, vendor_name, NULL);
|
||||
fx_stream_write_cstr(id, vendor_name, NULL);
|
||||
}
|
||||
|
||||
if (error_name) {
|
||||
if (vendor_name) {
|
||||
fx_stream_write_string(id, ".", NULL);
|
||||
fx_stream_write_cstr(id, ".", NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_string(id, error_name, NULL);
|
||||
fx_stream_write_cstr(id, error_name, NULL);
|
||||
} else {
|
||||
if (vendor_name) {
|
||||
fx_stream_write_string(id, "#", NULL);
|
||||
fx_stream_write_cstr(id, "#", NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_fmt(id, NULL, "%ld", code);
|
||||
@@ -125,6 +125,10 @@ static void print_content(
|
||||
const struct fx_error_template_parameter *params, size_t nr_params,
|
||||
const char *s)
|
||||
{
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
char modifier = 0;
|
||||
char buf[128];
|
||||
size_t buf_len = 0;
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@ static fx_status print_paragraph_tty(
|
||||
indent(format, tty, left_margin);
|
||||
}
|
||||
|
||||
fx_tty_puts(tty, 0, fx_string_ptr(line));
|
||||
fx_tty_puts(tty, 0, fx_string_get_cstr(line));
|
||||
fx_tty_putc(tty, 0, '\n');
|
||||
need_indent = true;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include "../../print.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include "../../tty.h"
|
||||
|
||||
#include <fx/term/tty.h>
|
||||
|
||||
@@ -158,7 +158,7 @@ void test_stringstream_1(CuTest *tc)
|
||||
char buf[1024];
|
||||
fx_stringstream *s = fx_stringstream_create_with_buffer(buf, sizeof buf);
|
||||
|
||||
fx_stream_write_string(s, "hello", NULL);
|
||||
fx_stream_write_cstr(s, "hello", NULL);
|
||||
fx_stream_write_fmt(s, NULL, "(%d + %.1f)", 32, 2.3);
|
||||
|
||||
char *end = fx_stringstream_steal(s);
|
||||
@@ -172,14 +172,14 @@ void test_stringstream_2(CuTest *tc)
|
||||
char buf[1024];
|
||||
fx_stringstream *s = fx_stringstream_create_with_buffer(buf, sizeof buf);
|
||||
|
||||
fx_stream_write_string(s, "{\n", NULL);
|
||||
fx_stream_write_cstr(s, "{\n", NULL);
|
||||
fx_stream_push_indent(s, 1);
|
||||
|
||||
fx_stream_write_string(s, "a = 32,\n", NULL);
|
||||
fx_stream_write_string(s, "b = 64\n", NULL);
|
||||
fx_stream_write_cstr(s, "a = 32,\n", NULL);
|
||||
fx_stream_write_cstr(s, "b = 64\n", NULL);
|
||||
|
||||
fx_stream_pop_indent(s);
|
||||
fx_stream_write_string(s, "}", NULL);
|
||||
fx_stream_write_cstr(s, "}", NULL);
|
||||
|
||||
char *str = fx_stringstream_steal(s);
|
||||
fx_stringstream_unref(s);
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@ static void test_string_create(CuTest *tc)
|
||||
|
||||
CuAssertPtrNotNull(tc, str);
|
||||
CuAssertIntEquals(tc, 0, fx_string_get_size(str, FX_STRLEN_NORMAL));
|
||||
CuAssertStrEquals(tc, "", fx_string_ptr(str));
|
||||
CuAssertStrEquals(tc, "", fx_string_get_cstr(str));
|
||||
|
||||
fx_string_unref(str);
|
||||
|
||||
@@ -15,7 +15,7 @@ static void test_string_create(CuTest *tc)
|
||||
|
||||
CuAssertPtrNotNull(tc, str);
|
||||
CuAssertIntEquals(tc, 8, fx_string_get_size(str, FX_STRLEN_NORMAL));
|
||||
CuAssertStrEquals(tc, "AAAAAAAA", fx_string_ptr(str));
|
||||
CuAssertStrEquals(tc, "AAAAAAAA", fx_string_get_cstr(str));
|
||||
|
||||
fx_string_unref(str);
|
||||
|
||||
@@ -23,7 +23,7 @@ static void test_string_create(CuTest *tc)
|
||||
|
||||
CuAssertPtrNotNull(tc, str);
|
||||
CuAssertIntEquals(tc, 13, fx_string_get_size(str, FX_STRLEN_NORMAL));
|
||||
CuAssertStrEquals(tc, "Hello, world!", fx_string_ptr(str));
|
||||
CuAssertStrEquals(tc, "Hello, world!", fx_string_get_cstr(str));
|
||||
|
||||
fx_string_unref(str);
|
||||
}
|
||||
|
||||
+6
-6
@@ -7,21 +7,21 @@ int main(void)
|
||||
{
|
||||
printf("-------------\n");
|
||||
fx_string *str = fx_string_create_from_cstr("Hello, world!\n");
|
||||
printf("%s\n", fx_string_ptr(str));
|
||||
printf("%s\n", fx_string_get_cstr(str));
|
||||
printf("len:%zu, max:%zu\n", fx_string_get_size(str, FX_STRLEN_NORMAL),
|
||||
fx_string_get_capacity(str));
|
||||
|
||||
fx_string_insert_cstr(str, "WOW!", 4);
|
||||
|
||||
printf("-------------\n");
|
||||
printf("%s\n", fx_string_ptr(str));
|
||||
printf("%s\n", fx_string_get_cstr(str));
|
||||
printf("len:%zu, max:%zu\n", fx_string_get_size(str, FX_STRLEN_NORMAL),
|
||||
fx_string_get_capacity(str));
|
||||
|
||||
fx_string_replace(str, 4, 4, "+");
|
||||
|
||||
printf("-------------\n");
|
||||
printf("%s\n", fx_string_ptr(str));
|
||||
printf("%s\n", fx_string_get_cstr(str));
|
||||
printf("len:%zu, max:%zu\n", fx_string_get_size(str, FX_STRLEN_NORMAL),
|
||||
fx_string_get_capacity(str));
|
||||
printf("-------------\n");
|
||||
@@ -29,9 +29,9 @@ int main(void)
|
||||
fx_string_unref(str);
|
||||
|
||||
fx_stringstream *strv = fx_stringstream_create();
|
||||
fx_stream_write_string(strv, "Hello", NULL);
|
||||
fx_stream_write_string(strv, ", world", NULL);
|
||||
fx_stream_write_string(strv, "!", NULL);
|
||||
fx_stream_write_cstr(strv, "Hello", NULL);
|
||||
fx_stream_write_cstr(strv, ", world", NULL);
|
||||
fx_stream_write_cstr(strv, "!", NULL);
|
||||
|
||||
char *s = fx_stringstream_steal(strv);
|
||||
fx_stringstream_unref(strv);
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ int main(void)
|
||||
size_t i = 0;
|
||||
fx_foreach(fx_dict_item *, item, it)
|
||||
{
|
||||
printf("item %zu: %s=%d\n", i++, fx_string_ptr(item->key),
|
||||
printf("item %zu: %s=%d\n", i++, fx_string_get_cstr(item->key),
|
||||
fx_number_get_int(item->value));
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ int main(void)
|
||||
{
|
||||
printf("здравс\u26A0твуите\n");
|
||||
fx_string *str = fx_string_create_from_cstr("здравствуите");
|
||||
const char *s = fx_string_ptr(str);
|
||||
const char *s = fx_string_get_cstr(str);
|
||||
printf("%s\n", s);
|
||||
printf("len: %zu\n", fx_string_get_size(str, FX_STRLEN_NORMAL));
|
||||
printf("codepoints: %zu\n", fx_string_get_size(str, FX_STRLEN_CODEPOINTS));
|
||||
|
||||
+3
-3
@@ -23,9 +23,9 @@ int main(int argc, const char **argv)
|
||||
fx_serial_ctx *ctx = NULL;
|
||||
|
||||
fx_object *data;
|
||||
fx_status status = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr, "cannot read data\n");
|
||||
result = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+68
-42
@@ -10,7 +10,7 @@ void write_tagged_value(fx_object *data);
|
||||
|
||||
void write_raw_string(const fx_string *data)
|
||||
{
|
||||
fx_stream_write_string(fx_stdout, "\"", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "\"", NULL);
|
||||
|
||||
const fx_iterator *it = fx_iterator_cbegin(data);
|
||||
fx_foreach_c(fx_wchar, c, it)
|
||||
@@ -19,7 +19,12 @@ void write_raw_string(const fx_string *data)
|
||||
c -= 0x10000;
|
||||
long hi = 0xD800 | ((c >> 10) & 0x3FF);
|
||||
long lo = 0xDC00 | (c & 0x3FF);
|
||||
fx_stream_write_fmt(fx_stdout, NULL, "\\u%04x\\u%04x", hi, lo);
|
||||
fx_stream_write_fmt(
|
||||
fx_stdout,
|
||||
NULL,
|
||||
"\\u%04x\\u%04x",
|
||||
hi,
|
||||
lo);
|
||||
} else if (c <= 0x1F || c >= 0x7F) {
|
||||
fx_stream_write_fmt(fx_stdout, NULL, "\\u%04x", c);
|
||||
} else if (c == '\\' || c == '"') {
|
||||
@@ -30,52 +35,63 @@ void write_raw_string(const fx_string *data)
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_stream_write_string(fx_stdout, "\"", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "\"", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_string(fx_string *data)
|
||||
{
|
||||
fx_stream_write_string(fx_stdout, "{ \"type\": \"string\", \"value\": ", NULL);
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
"{ \"type\": \"string\", \"value\": ",
|
||||
NULL);
|
||||
|
||||
write_raw_string(data);
|
||||
|
||||
fx_stream_write_string(fx_stdout, " }", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, " }", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_integer(fx_number *data)
|
||||
{
|
||||
fx_stream_write_string(
|
||||
fx_stdout, "{ \"type\": \"integer\", \"value\": \"", NULL);
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
"{ \"type\": \"integer\", \"value\": \"",
|
||||
NULL);
|
||||
|
||||
if (fx_number_is_inf_positive(data)) {
|
||||
fx_stream_write_string(fx_stdout, "inf", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "inf", NULL);
|
||||
} else if (fx_number_is_inf_negative(data)) {
|
||||
fx_stream_write_string(fx_stdout, "-inf", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "-inf", NULL);
|
||||
} else if (fx_number_is_nan_positive(data)) {
|
||||
fx_stream_write_string(fx_stdout, "nan", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "nan", NULL);
|
||||
} else if (fx_number_is_nan_negative(data)) {
|
||||
fx_stream_write_string(fx_stdout, "-nan", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "-nan", NULL);
|
||||
} else {
|
||||
fx_stream_write_fmt(
|
||||
fx_stdout, NULL, "%lld", fx_number_get_longlong(data), NULL);
|
||||
fx_stdout,
|
||||
NULL,
|
||||
"%lld",
|
||||
fx_number_get_longlong(data),
|
||||
NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_string(fx_stdout, "\" }", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "\" }", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_float(fx_number *data)
|
||||
{
|
||||
fx_stream_write_string(
|
||||
fx_stdout, "{ \"type\": \"float\", \"value\": \"", NULL);
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
"{ \"type\": \"float\", \"value\": \"",
|
||||
NULL);
|
||||
|
||||
if (fx_number_is_inf_positive(data)) {
|
||||
fx_stream_write_string(fx_stdout, "inf", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "inf", NULL);
|
||||
} else if (fx_number_is_inf_negative(data)) {
|
||||
fx_stream_write_string(fx_stdout, "-inf", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "-inf", NULL);
|
||||
} else if (fx_number_is_nan_positive(data)) {
|
||||
fx_stream_write_string(fx_stdout, "nan", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "nan", NULL);
|
||||
} else if (fx_number_is_nan_negative(data)) {
|
||||
fx_stream_write_string(fx_stdout, "-nan", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "-nan", NULL);
|
||||
} else {
|
||||
double v = fx_number_get_double(data);
|
||||
if ((v <= 0.00000001 && v > 0) || (v >= -0.00000001 && v < 0)
|
||||
@@ -86,15 +102,18 @@ void write_tagged_float(fx_number *data)
|
||||
}
|
||||
}
|
||||
|
||||
fx_stream_write_string(fx_stdout, "\" }", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "\" }", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_bool(fx_number *data)
|
||||
{
|
||||
int v = fx_number_get_int8(data);
|
||||
fx_stream_write_fmt(
|
||||
fx_stdout, NULL, "{ \"type\": \"bool\", \"value\": \"%s\" }",
|
||||
(v > 0) ? "true" : "false", NULL);
|
||||
fx_stdout,
|
||||
NULL,
|
||||
"{ \"type\": \"bool\", \"value\": \"%s\" }",
|
||||
(v > 0) ? "true" : "false",
|
||||
NULL);
|
||||
}
|
||||
|
||||
void write_tagged_datetime(fx_datetime *data)
|
||||
@@ -103,33 +122,39 @@ void write_tagged_datetime(fx_datetime *data)
|
||||
bool has_time = fx_datetime_has_time(data);
|
||||
bool localtime = fx_datetime_is_localtime(data);
|
||||
|
||||
fx_stream_write_string(fx_stdout, "{ \"type\": \"", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "{ \"type\": \"", NULL);
|
||||
|
||||
if (has_date && has_time) {
|
||||
fx_stream_write_string(
|
||||
fx_stdout, localtime ? "datetime-local" : "datetime", NULL);
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
localtime ? "datetime-local" : "datetime",
|
||||
NULL);
|
||||
} else if (has_date) {
|
||||
fx_stream_write_string(
|
||||
fx_stdout, localtime ? "date-local" : "date", NULL);
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
localtime ? "date-local" : "date",
|
||||
NULL);
|
||||
} else if (has_time) {
|
||||
fx_stream_write_string(
|
||||
fx_stdout, localtime ? "time-local" : "time", NULL);
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
localtime ? "time-local" : "time",
|
||||
NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_string(fx_stdout, "\", \"value\": \"", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "\", \"value\": \"", NULL);
|
||||
|
||||
fx_string *new_data = fx_string_create();
|
||||
fx_datetime_to_string(data, FX_DATETIME_FORMAT_RFC3339, new_data);
|
||||
fx_stream_write_string(fx_stdout, fx_string_ptr(new_data), NULL);
|
||||
fx_stream_write_cstr(fx_stdout, fx_string_get_cstr(new_data), NULL);
|
||||
|
||||
fx_stream_write_string(fx_stdout, "\" }", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "\" }", NULL);
|
||||
|
||||
fx_string_unref(new_data);
|
||||
}
|
||||
|
||||
void write_tagged_dict(fx_dict *data)
|
||||
{
|
||||
fx_stream_write_string(fx_stdout, "{ ", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "{ ", NULL);
|
||||
|
||||
int i = 0;
|
||||
|
||||
@@ -137,35 +162,35 @@ void write_tagged_dict(fx_dict *data)
|
||||
fx_foreach(fx_dict_item *, item, it)
|
||||
{
|
||||
if (i++ > 0) {
|
||||
fx_stream_write_string(fx_stdout, ", ", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, ", ", NULL);
|
||||
}
|
||||
|
||||
write_raw_string(item->key);
|
||||
fx_stream_write_string(fx_stdout, ": ", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, ": ", NULL);
|
||||
write_tagged_value(item->value);
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_stream_write_string(fx_stdout, " }", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, " }", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_array(fx_array *data)
|
||||
{
|
||||
fx_stream_write_string(fx_stdout, "[ ", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, "[ ", NULL);
|
||||
|
||||
int i = 0;
|
||||
fx_iterator *it = fx_iterator_begin(data);
|
||||
fx_foreach(fx_object *, obj, it)
|
||||
{
|
||||
if (i++ > 0) {
|
||||
fx_stream_write_string(fx_stdout, ", ", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, ", ", NULL);
|
||||
}
|
||||
|
||||
write_tagged_value(obj);
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_stream_write_string(fx_stdout, " ]", NULL);
|
||||
fx_stream_write_cstr(fx_stdout, " ]", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_value(fx_object *data)
|
||||
@@ -207,9 +232,10 @@ int main(void)
|
||||
fx_serial_ctx *ctx = fx_toml_serial_ctx_create();
|
||||
|
||||
fx_object *data;
|
||||
fx_status status = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||
if (!FX_OK(status)) {
|
||||
return 1;
|
||||
fx_result result = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_tagged_value(data);
|
||||
|
||||
+3
-3
@@ -23,9 +23,9 @@ int main(int argc, const char **argv)
|
||||
fx_serial_ctx *ctx = fx_toml_serial_ctx_create();
|
||||
|
||||
fx_object *data = NULL;
|
||||
fx_status status = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr, "cannot read data\n");
|
||||
result = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user