meta: re-organise tests
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
file(GLOB test_sources *.c)
|
||||
|
||||
foreach (f ${test_sources})
|
||||
get_filename_component(test_name ${f} NAME_WLE)
|
||||
add_executable(${test_name} ${f})
|
||||
target_link_libraries(${test_name} ${fx_assemblies})
|
||||
endforeach (f)
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
printf("dynamic loader\n");
|
||||
void *assembly = dlopen(argv[1], RTLD_LAZY);
|
||||
if (!assembly) {
|
||||
printf("cannot load %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const void *(*asm_info)(void) = dlsym(assembly, "__fx_assembly_get");
|
||||
if (!asm_info) {
|
||||
printf("cannot find assembly info for %s", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
asm_info();
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
#include <fx/core/stream.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/io/file.h>
|
||||
#include <fx/io/path.h>
|
||||
#include <fx/stream.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/stringstream.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
#include <fx/core/stream.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/io/file.h>
|
||||
#include <fx/io/path.h>
|
||||
#include <fx/stream.h>
|
||||
#include <fx/string.h>
|
||||
#include <fx/stringstream.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
#include <fx/cmd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum {
|
||||
CMD_TEST,
|
||||
CMD_SUB,
|
||||
OPT_NAME,
|
||||
OPT_NAME_VALUE,
|
||||
OPT_OTHER,
|
||||
OPT_OTHER_VALUE,
|
||||
OPT_VERBOSE,
|
||||
OPT_REALLY_VERBOSE,
|
||||
OPT_MODE,
|
||||
OPT_MODE_VALUE,
|
||||
OPT_MODE_VALUE2,
|
||||
ARG_FILE,
|
||||
ARG_MORE,
|
||||
};
|
||||
|
||||
const char *text
|
||||
= "No one rejects, dislikes, or avoids pleasure itself, because it is "
|
||||
"pleasure, but because those who do not know how to pursue pleasure "
|
||||
"rationally encounter consequences that are extremely painful. Nor "
|
||||
"again is there anyone who loves or pursues or desires to obtain "
|
||||
"pain of itself, because it is pain, but because occasionally "
|
||||
"circumstances occur in which toil and pain can procure him some "
|
||||
"great pleasure.";
|
||||
|
||||
static int test_command(
|
||||
const fx_command *self, const fx_arglist *opt, const fx_array *args)
|
||||
{
|
||||
printf("Hello, world!\n");
|
||||
|
||||
fx_arglist_iterator it;
|
||||
fx_arglist_iterator_begin(
|
||||
opt, FX_COMMAND_INVALID_ID, FX_COMMAND_INVALID_ID, &it);
|
||||
while (fx_arglist_iterator_is_valid(&it)) {
|
||||
printf("opt:%u,arg:%u,i:%zu,value: %s\n", it.opt_id,
|
||||
it.value->val_id, it.i, it.value->val_str);
|
||||
|
||||
fx_arglist_iterator_next(&it);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FX_COMMAND(CMD_TEST, FX_COMMAND_INVALID_ID)
|
||||
{
|
||||
FX_COMMAND_NAME("test");
|
||||
FX_COMMAND_DESC("A test command.");
|
||||
FX_COMMAND_FLAGS(FX_COMMAND_SHOW_HELP_BY_DEFAULT);
|
||||
FX_COMMAND_FUNCTION(test_command);
|
||||
|
||||
FX_COMMAND_OPTION(OPT_NAME)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("name");
|
||||
FX_OPTION_SHORT_NAME('n');
|
||||
FX_OPTION_DESC("The name of the data.");
|
||||
FX_OPTION_ARG(OPT_NAME_VALUE)
|
||||
{
|
||||
FX_ARG_NAME("name");
|
||||
FX_ARG_NR_VALUES(2);
|
||||
}
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_OTHER)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("other");
|
||||
FX_OPTION_DESC(text);
|
||||
|
||||
FX_OPTION_ARG(OPT_OTHER_VALUE)
|
||||
{
|
||||
FX_ARG_NAME("value");
|
||||
FX_ARG_NR_VALUES(FX_ARG_1_OR_MORE_VALUES);
|
||||
}
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_VERBOSE)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("verbose");
|
||||
FX_OPTION_SHORT_NAME('v');
|
||||
FX_OPTION_DESC("Show detailed log output.");
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_REALLY_VERBOSE)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("really-verbose");
|
||||
FX_OPTION_SHORT_NAME('V');
|
||||
FX_OPTION_DESC("Show REALLY detailed log output.");
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_MODE)
|
||||
{
|
||||
FX_OPTION_SHORT_NAME('m');
|
||||
FX_OPTION_LONG_NAME("mode");
|
||||
FX_OPTION_DESC("modes to operate in.");
|
||||
|
||||
FX_OPTION_ARG(OPT_MODE_VALUE)
|
||||
{
|
||||
FX_ARG_NAME("mode");
|
||||
FX_ARG_NR_VALUES(1);
|
||||
FX_ARG_ALLOWED_VALUES("fast", "slow");
|
||||
}
|
||||
|
||||
FX_OPTION_ARG(OPT_MODE_VALUE2)
|
||||
{
|
||||
FX_ARG_NAME("mode2");
|
||||
FX_ARG_NR_VALUES(1);
|
||||
FX_ARG_ALLOWED_VALUES("very-fast", "very-slow");
|
||||
}
|
||||
}
|
||||
|
||||
FX_COMMAND_ARG(ARG_FILE)
|
||||
{
|
||||
FX_ARG_NAME("file");
|
||||
FX_ARG_DESC("The file(s) to use");
|
||||
FX_ARG_NR_VALUES(2);
|
||||
}
|
||||
|
||||
FX_COMMAND_ARG(ARG_MORE)
|
||||
{
|
||||
FX_ARG_NAME("more");
|
||||
FX_ARG_DESC("More args to use");
|
||||
FX_ARG_ALLOWED_VALUES("how", "wow");
|
||||
FX_ARG_NR_VALUES(2);
|
||||
}
|
||||
|
||||
FX_COMMAND_HELP_OPTION();
|
||||
|
||||
FX_COMMAND_USAGE()
|
||||
{
|
||||
FX_COMMAND_USAGE_OPT(OPT_NAME);
|
||||
FX_COMMAND_USAGE_ARG(ARG_FILE);
|
||||
FX_COMMAND_USAGE_ARG(ARG_MORE);
|
||||
}
|
||||
}
|
||||
|
||||
FX_COMMAND(CMD_SUB, CMD_TEST)
|
||||
{
|
||||
FX_COMMAND_NAME("sub");
|
||||
FX_COMMAND_LONG_NAME("sub");
|
||||
FX_COMMAND_SHORT_NAME('S');
|
||||
FX_COMMAND_DESC("A test subcommand");
|
||||
FX_COMMAND_FLAGS(FX_COMMAND_SHOW_HELP_BY_DEFAULT);
|
||||
FX_COMMAND_FUNCTION(test_command);
|
||||
|
||||
FX_COMMAND_OPTION(OPT_NAME)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("name");
|
||||
FX_OPTION_SHORT_NAME('n');
|
||||
FX_OPTION_DESC("The name of the data");
|
||||
FX_OPTION_ARG(OPT_NAME_VALUE)
|
||||
{
|
||||
FX_ARG_NAME("name");
|
||||
}
|
||||
}
|
||||
|
||||
FX_COMMAND_OPTION(OPT_OTHER)
|
||||
{
|
||||
FX_OPTION_LONG_NAME("other");
|
||||
FX_OPTION_SHORT_NAME('o');
|
||||
FX_OPTION_DESC("The other argument");
|
||||
FX_OPTION_ARG(OPT_OTHER_VALUE)
|
||||
{
|
||||
FX_ARG_NAME("value");
|
||||
}
|
||||
}
|
||||
|
||||
FX_COMMAND_HELP_OPTION();
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
return fx_command_dispatch(CMD_TEST, argc, argv);
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <fx/compress/compressor.h>
|
||||
#include <fx/compress/cstream.h>
|
||||
#include <fx/compress/zstd.h>
|
||||
#include <fx/core/ringbuffer.h>
|
||||
#include <fx/core/stream.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NR_ITERATIONS 10
|
||||
|
||||
static const char source[]
|
||||
= "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sodales "
|
||||
"scelerisque lacus. In ullamcorper sem a nibh venenatis efficitur at "
|
||||
"id quam. Nam quis urna nulla. In in consectetur ligula. Morbi "
|
||||
"ligula neque, imperdiet quis erat et, mollis consequat sapien. "
|
||||
"Vivamus quis bibendum nulla. Vivamus tincidunt mauris sed nisl "
|
||||
"vulputate pellentesque. Nam blandit ac risus ut auctor. Fusce "
|
||||
"sagittis quam ut sapien accumsan, pellentesque finibus elit "
|
||||
"eleifend. Duis sodales ex urna, a porttitor ex bibendum quis quam.";
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s <outpath>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_compressor_mode mode = FX_COMPRESSOR_MODE_COMPRESS;
|
||||
|
||||
FILE *out_fp = fopen(argv[1], "wb");
|
||||
if (!out_fp) {
|
||||
fprintf(stderr, "cannot open output file %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_stream *out_stream = fx_stream_open_fp(out_fp);
|
||||
fx_cstream *cstream;
|
||||
fx_cstream_open(out_stream, FX_TYPE_ZSTD_COMPRESSOR, mode, &cstream);
|
||||
|
||||
const size_t source_len = strlen(source);
|
||||
bool compressed = false;
|
||||
|
||||
for (int i = 0; i < NR_ITERATIONS; i++) {
|
||||
if (compressed) {
|
||||
fx_cstream_begin_compressed_section(cstream, NULL);
|
||||
}
|
||||
|
||||
size_t nr_written = 0;
|
||||
fx_status status = fx_cstream_write(
|
||||
cstream, source, source_len, &nr_written);
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr, "write error: %s\n",
|
||||
fx_status_description(status));
|
||||
break;
|
||||
}
|
||||
|
||||
size_t nr_written_compressed = 0;
|
||||
|
||||
if (compressed) {
|
||||
fx_cstream_end_compressed_section(
|
||||
cstream, &nr_written_compressed, &nr_written);
|
||||
}
|
||||
|
||||
size_t tx_total = 0;
|
||||
fx_cstream_tx_bytes(cstream, &tx_total);
|
||||
printf("iteration %d: wrote %zu (compressed) / %zu "
|
||||
"(uncompressed) / %zu (total) bytes (%s)\n",
|
||||
i, nr_written_compressed, nr_written, tx_total,
|
||||
compressed ? "compressed" : "uncompressed");
|
||||
|
||||
compressed = !compressed;
|
||||
}
|
||||
|
||||
printf("Done\n");
|
||||
|
||||
fx_cstream_unref(cstream);
|
||||
fx_stream_unref(out_stream);
|
||||
fclose(out_fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <fx/compress/compressor.h>
|
||||
#include <fx/compress/cstream.h>
|
||||
#include <fx/compress/zstd.h>
|
||||
#include <fx/core/ringbuffer.h>
|
||||
#include <fx/core/stream.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s <inpath>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_compressor_mode mode = FX_COMPRESSOR_MODE_DECOMPRESS;
|
||||
|
||||
FILE *in_fp = fopen(argv[1], "rb");
|
||||
if (!in_fp) {
|
||||
fprintf(stderr, "cannot open input file %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_stream *in_stream = fx_stream_open_fp(in_fp);
|
||||
fx_cstream *cstream;
|
||||
fx_cstream_open(in_stream, FX_TYPE_ZSTD_COMPRESSOR, mode, &cstream);
|
||||
|
||||
bool compressed = false;
|
||||
char buf[513];
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
if (compressed) {
|
||||
fx_cstream_begin_compressed_section(cstream, NULL);
|
||||
}
|
||||
|
||||
memset(buf, 0x0, sizeof buf);
|
||||
|
||||
size_t nr_read = 0;
|
||||
fx_status status
|
||||
= fx_cstream_read(cstream, buf, sizeof buf - 1, &nr_read);
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr, "write error: %s\n",
|
||||
fx_status_description(status));
|
||||
break;
|
||||
}
|
||||
|
||||
if (nr_read == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t nr_read_compressed = 0;
|
||||
if (compressed) {
|
||||
fx_cstream_end_compressed_section(
|
||||
cstream, &nr_read_compressed, &nr_read);
|
||||
}
|
||||
|
||||
size_t tx_total = 0;
|
||||
fx_cstream_tx_bytes(cstream, &tx_total);
|
||||
printf(" * iteration %d: read %zu (compressed) / %zu "
|
||||
"(uncompressed) / %zu (total) bytes (%s)\n",
|
||||
i, nr_read_compressed, nr_read, tx_total,
|
||||
compressed ? "compressed" : "uncompressed");
|
||||
printf("%s\n", buf);
|
||||
|
||||
compressed = !compressed;
|
||||
}
|
||||
|
||||
printf("Done\n");
|
||||
|
||||
fx_cstream_unref(cstream);
|
||||
fx_stream_unref(in_stream);
|
||||
fclose(in_fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <fx/compress/compressor.h>
|
||||
#include <fx/compress/zstd.h>
|
||||
#include <fx/core/ringbuffer.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUF_SIZE 32
|
||||
|
||||
int refill_input_buffer(FILE *fp, fx_ringbuffer *dest)
|
||||
{
|
||||
while (1) {
|
||||
void *buf;
|
||||
size_t capacity;
|
||||
fx_status status
|
||||
= fx_ringbuffer_open_write_buffer(dest, &buf, &capacity);
|
||||
if (status == FX_ERR_NO_SPACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t r = fread(buf, 1, capacity, fp);
|
||||
|
||||
fx_ringbuffer_close_write_buffer(dest, &buf, r);
|
||||
|
||||
if (r == 0) {
|
||||
return ferror(fp) ? -1 : 0;
|
||||
}
|
||||
|
||||
if (r < capacity) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flush_output_buffer(FILE *fp, fx_ringbuffer *src)
|
||||
{
|
||||
while (1) {
|
||||
const void *buf;
|
||||
size_t capacity;
|
||||
fx_status status
|
||||
= fx_ringbuffer_open_read_buffer(src, &buf, &capacity);
|
||||
if (status == FX_ERR_NO_DATA) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t w = fwrite(buf, 1, capacity, fp);
|
||||
|
||||
fx_ringbuffer_close_read_buffer(src, &buf, w);
|
||||
|
||||
if (w < capacity) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "usage: %s <C/D> <inpath> <outpath>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_compressor_mode mode;
|
||||
if (!strcmp(argv[1], "C")) {
|
||||
mode = FX_COMPRESSOR_MODE_COMPRESS;
|
||||
} else if (!strcmp(argv[1], "D")) {
|
||||
mode = FX_COMPRESSOR_MODE_DECOMPRESS;
|
||||
} else {
|
||||
fprintf(stderr, "invalid mode %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *in_fp = fopen(argv[2], "rb");
|
||||
if (!in_fp) {
|
||||
fprintf(stderr, "cannot open input file %s\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *out_fp = fopen(argv[3], "wb");
|
||||
if (!out_fp) {
|
||||
fclose(in_fp);
|
||||
fprintf(stderr, "cannot open output file %s\n", argv[3]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_status status = FX_SUCCESS;
|
||||
fx_type compressor_type = FX_TYPE_ZSTD_COMPRESSOR;
|
||||
fx_compressor *compressor = fx_object_create(compressor_type);
|
||||
|
||||
size_t inbuf_size, outbuf_size;
|
||||
fx_compressor_get_buffer_size(
|
||||
compressor_type, mode, &inbuf_size, &outbuf_size);
|
||||
|
||||
fx_ringbuffer *in = fx_ringbuffer_create(inbuf_size);
|
||||
fx_ringbuffer *out = fx_ringbuffer_create(outbuf_size);
|
||||
|
||||
if (!in || !out) {
|
||||
fprintf(stderr, "memory allocation failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_compressor_set_buffer(compressor, in, out);
|
||||
fx_compressor_set_mode(compressor, mode);
|
||||
|
||||
int ret = 0;
|
||||
while (1) {
|
||||
ret = refill_input_buffer(in_fp, in);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "read error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fx_ringbuffer_available_data_remaining(in)) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = fx_compressor_step(compressor);
|
||||
|
||||
if (status == FX_ERR_NO_DATA) {
|
||||
break;
|
||||
} else if (status == FX_ERR_NO_SPACE) {
|
||||
ret = flush_output_buffer(out_fp, out);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "write error\n");
|
||||
break;
|
||||
}
|
||||
} else if (!FX_OK(status)) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = flush_output_buffer(out_fp, out);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "write error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode == FX_COMPRESSOR_MODE_COMPRESS) {
|
||||
while (!fx_compressor_eof(compressor)) {
|
||||
status = fx_compressor_end(compressor);
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr,
|
||||
"compression finalisation error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!fx_ringbuffer_available_data_remaining(out)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = flush_output_buffer(out_fp, out);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "write error\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Done\n");
|
||||
|
||||
fx_compressor_unref(compressor);
|
||||
|
||||
fclose(in_fp);
|
||||
fclose(out_fp);
|
||||
|
||||
fx_ringbuffer_unref(in);
|
||||
fx_ringbuffer_unref(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <fx/compress/compressor.h>
|
||||
#include <fx/compress/cstream.h>
|
||||
#include <fx/compress/zstd.h>
|
||||
#include <fx/core/ringbuffer.h>
|
||||
#include <fx/core/stream.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUF_SIZE 32
|
||||
|
||||
static int compress(fx_type compressor_type, FILE *in, FILE *out)
|
||||
{
|
||||
fx_stream *out_stream = fx_stream_open_fp(out);
|
||||
|
||||
fx_cstream *cstream;
|
||||
fx_status status = fx_cstream_open(
|
||||
out_stream, compressor_type, FX_COMPRESSOR_MODE_COMPRESS, &cstream);
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr, "cannot initialise compressor\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_cstream_begin_compressed_section(cstream, NULL);
|
||||
|
||||
char buf[4096];
|
||||
while (1) {
|
||||
size_t r = fread(buf, 1, sizeof buf, in);
|
||||
|
||||
size_t w = 0;
|
||||
fx_cstream_write(cstream, buf, r, &w);
|
||||
|
||||
if (r != w) {
|
||||
fprintf(stderr, "write error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (r < sizeof buf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fx_cstream_end_compressed_section(cstream, NULL, NULL);
|
||||
fx_cstream_unref(cstream);
|
||||
fx_stream_unref(out_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decompress(fx_type compressor_type, FILE *in, FILE *out)
|
||||
{
|
||||
fx_stream *in_stream = fx_stream_open_fp(in);
|
||||
|
||||
fx_cstream *cstream;
|
||||
fx_status status = fx_cstream_open(
|
||||
in_stream, compressor_type, FX_COMPRESSOR_MODE_DECOMPRESS, &cstream);
|
||||
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr, "cannot initialise compressor\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_cstream_begin_compressed_section(cstream, NULL);
|
||||
|
||||
char buf[4096];
|
||||
while (1) {
|
||||
size_t r = 0;
|
||||
fx_status status = fx_cstream_read(cstream, buf, sizeof buf, &r);
|
||||
if (!FX_OK(status)) {
|
||||
fprintf(stderr, "read error: %s\n",
|
||||
fx_status_description(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t w = fwrite(buf, 1, r, out);
|
||||
if (r != w) {
|
||||
fprintf(stderr, "write error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (r < sizeof buf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fx_cstream_end_compressed_section(cstream, NULL, NULL);
|
||||
fx_cstream_unref(cstream);
|
||||
fx_stream_unref(in_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "usage: %s <C/D> <inpath> <outpath>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_compressor_mode mode;
|
||||
if (!strcmp(argv[1], "C")) {
|
||||
mode = FX_COMPRESSOR_MODE_COMPRESS;
|
||||
} else if (!strcmp(argv[1], "D")) {
|
||||
mode = FX_COMPRESSOR_MODE_DECOMPRESS;
|
||||
} else {
|
||||
fprintf(stderr, "invalid mode %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *in_fp = fopen(argv[2], "rb");
|
||||
if (!in_fp) {
|
||||
fprintf(stderr, "cannot open input file %s\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *out_fp = fopen(argv[3], "wb");
|
||||
if (!out_fp) {
|
||||
fclose(in_fp);
|
||||
fprintf(stderr, "cannot open output file %s\n", argv[3]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
switch (mode) {
|
||||
case FX_COMPRESSOR_MODE_COMPRESS:
|
||||
ret = compress(FX_TYPE_ZSTD_COMPRESSOR, in_fp, out_fp);
|
||||
break;
|
||||
case FX_COMPRESSOR_MODE_DECOMPRESS:
|
||||
ret = decompress(FX_TYPE_ZSTD_COMPRESSOR, in_fp, out_fp);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Done\n");
|
||||
|
||||
fclose(in_fp);
|
||||
fclose(out_fp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
#include <CuTest.h>
|
||||
#include <fx/core/bst.h>
|
||||
#include <fx/core/misc.h>
|
||||
#include <fx/core/queue.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
struct test_tree_node {
|
||||
int value;
|
||||
fx_bst_node node;
|
||||
};
|
||||
|
||||
struct test_queue_entry {
|
||||
int value;
|
||||
fx_queue_entry entry;
|
||||
};
|
||||
|
||||
FX_BST_DEFINE_SIMPLE_INSERT(struct test_tree_node, node, value, test_tree_insert);
|
||||
|
||||
void test_bst_insert(CuTest *tc)
|
||||
{
|
||||
fx_bst tree = {0};
|
||||
struct test_tree_node nodes[3] = {0};
|
||||
|
||||
for (int i = 0; i < sizeof nodes / sizeof *nodes; i++) {
|
||||
nodes[i].value = i;
|
||||
}
|
||||
|
||||
test_tree_insert(&tree, &nodes[0]);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, nodes[0].node.n_left);
|
||||
CuAssertPtrEquals(tc, NULL, nodes[0].node.n_right);
|
||||
CuAssertIntEquals(tc, 1, nodes[0].node.n_height);
|
||||
|
||||
test_tree_insert(&tree, &nodes[1]);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, nodes[0].node.n_left);
|
||||
CuAssertPtrEquals(tc, &nodes[1].node, nodes[0].node.n_right);
|
||||
CuAssertIntEquals(tc, 2, nodes[0].node.n_height);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, nodes[1].node.n_left);
|
||||
CuAssertPtrEquals(tc, NULL, nodes[1].node.n_right);
|
||||
CuAssertIntEquals(tc, 1, nodes[1].node.n_height);
|
||||
|
||||
test_tree_insert(&tree, &nodes[2]);
|
||||
|
||||
CuAssertPtrEquals(tc, &nodes[0].node, nodes[1].node.n_left);
|
||||
CuAssertPtrEquals(tc, &nodes[2].node, nodes[1].node.n_right);
|
||||
CuAssertIntEquals(tc, 2, nodes[1].node.n_height);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, nodes[0].node.n_left);
|
||||
CuAssertPtrEquals(tc, NULL, nodes[0].node.n_right);
|
||||
CuAssertIntEquals(tc, 1, nodes[0].node.n_height);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, nodes[2].node.n_left);
|
||||
CuAssertPtrEquals(tc, NULL, nodes[2].node.n_right);
|
||||
CuAssertIntEquals(tc, 1, nodes[2].node.n_height);
|
||||
}
|
||||
|
||||
void test_bst_iterate(CuTest *tc)
|
||||
{
|
||||
static const size_t nr_nodes = 256;
|
||||
srand(time(NULL));
|
||||
|
||||
fx_bst tree = {0};
|
||||
struct test_tree_node *nodes = calloc(nr_nodes, sizeof *nodes);
|
||||
CuAssertPtrNotNull(tc, nodes);
|
||||
|
||||
for (int i = 0; i < nr_nodes; i++) {
|
||||
nodes[i].value = rand();
|
||||
test_tree_insert(&tree, &nodes[i]);
|
||||
}
|
||||
|
||||
int prev = -1;
|
||||
fx_bst_node *bnode = fx_bst_first(&tree);
|
||||
while (bnode) {
|
||||
struct test_tree_node *node
|
||||
= fx_unbox(struct test_tree_node, bnode, node);
|
||||
CuAssertPtrNotNull(tc, node);
|
||||
|
||||
if (prev == -1) {
|
||||
prev = node->value;
|
||||
bnode = fx_bst_next(bnode);
|
||||
continue;
|
||||
}
|
||||
|
||||
CuAssertTrue(tc, prev <= node->value);
|
||||
prev = node->value;
|
||||
bnode = fx_bst_next(bnode);
|
||||
}
|
||||
|
||||
free(nodes);
|
||||
}
|
||||
|
||||
void test_queue_insert(CuTest *tc)
|
||||
{
|
||||
struct test_queue_entry entries[5] = {0};
|
||||
for (int i = 0; i < sizeof entries / sizeof *entries; i++) {
|
||||
entries[i].value = i;
|
||||
}
|
||||
|
||||
fx_queue q = FX_QUEUE_INIT;
|
||||
|
||||
fx_queue_push_back(&q, &entries[0].entry);
|
||||
fx_queue_push_back(&q, &entries[2].entry);
|
||||
fx_queue_push_back(&q, &entries[4].entry);
|
||||
fx_queue_insert_after(&q, &entries[3].entry, &entries[2].entry);
|
||||
fx_queue_insert_before(&q, &entries[1].entry, &entries[2].entry);
|
||||
|
||||
CuAssertPtrEquals(tc, NULL, entries[0].entry.qe_prev);
|
||||
CuAssertPtrEquals(tc, &entries[1].entry, entries[0].entry.qe_next);
|
||||
|
||||
CuAssertPtrEquals(tc, &entries[0].entry, entries[1].entry.qe_prev);
|
||||
CuAssertPtrEquals(tc, &entries[2].entry, entries[1].entry.qe_next);
|
||||
|
||||
CuAssertPtrEquals(tc, &entries[1].entry, entries[2].entry.qe_prev);
|
||||
CuAssertPtrEquals(tc, &entries[3].entry, entries[2].entry.qe_next);
|
||||
|
||||
CuAssertPtrEquals(tc, &entries[2].entry, entries[3].entry.qe_prev);
|
||||
CuAssertPtrEquals(tc, &entries[4].entry, entries[3].entry.qe_next);
|
||||
|
||||
CuAssertPtrEquals(tc, &entries[3].entry, entries[4].entry.qe_prev);
|
||||
CuAssertPtrEquals(tc, NULL, entries[4].entry.qe_next);
|
||||
}
|
||||
|
||||
void test_queue_iterate(CuTest *tc)
|
||||
{
|
||||
fx_queue q = FX_QUEUE_INIT;
|
||||
struct test_queue_entry entries[32] = {0};
|
||||
|
||||
for (int i = 0; i < sizeof entries / sizeof *entries; i++) {
|
||||
entries[i].value = i;
|
||||
fx_queue_push_back(&q, &entries[i].entry);
|
||||
}
|
||||
|
||||
int prev = -1;
|
||||
struct fx_queue_entry *entry = fx_queue_first(&q);
|
||||
while (entry) {
|
||||
struct test_queue_entry *e
|
||||
= fx_unbox(struct test_queue_entry, entry, entry);
|
||||
CuAssertPtrNotNull(tc, e);
|
||||
|
||||
if (prev == -1) {
|
||||
prev = e->value;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
CuAssertTrue(tc, prev < e->value);
|
||||
prev = e->value;
|
||||
skip:
|
||||
entry = fx_queue_next(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void test_stringstream_1(CuTest *tc)
|
||||
{
|
||||
char buf[1024];
|
||||
fx_stringstream *s = fx_stringstream_create_with_buffer(buf, sizeof buf);
|
||||
|
||||
fx_stream_write_cstr(s, "hello", NULL);
|
||||
fx_stream_write_fmt(s, NULL, "(%d + %.1f)", 32, 2.3);
|
||||
|
||||
char *end = fx_stringstream_steal(s);
|
||||
fx_stringstream_unref(s);
|
||||
|
||||
CuAssertStrEquals(tc, "hello(32 + 2.3)", end);
|
||||
}
|
||||
|
||||
void test_stringstream_2(CuTest *tc)
|
||||
{
|
||||
char buf[1024];
|
||||
fx_stringstream *s = fx_stringstream_create_with_buffer(buf, sizeof buf);
|
||||
|
||||
fx_stream_write_cstr(s, "{\n", NULL);
|
||||
fx_stream_push_indent(s, 1);
|
||||
|
||||
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_cstr(s, "}", NULL);
|
||||
|
||||
char *str = fx_stringstream_steal(s);
|
||||
fx_stringstream_unref(s);
|
||||
|
||||
CuAssertStrEquals(tc, "{\n a = 32,\n b = 64\n}", str);
|
||||
}
|
||||
|
||||
CuSuite *get_all_tests(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
||||
SUITE_ADD_TEST(suite, test_bst_insert);
|
||||
SUITE_ADD_TEST(suite, test_bst_iterate);
|
||||
SUITE_ADD_TEST(suite, test_queue_insert);
|
||||
SUITE_ADD_TEST(suite, test_queue_iterate);
|
||||
SUITE_ADD_TEST(suite, test_stringstream_1);
|
||||
SUITE_ADD_TEST(suite, test_stringstream_2);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#include <fx/core/error.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
#include <fx/core/hash.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static void print_digest(
|
||||
const char *func_name, fx_hash_function func, const char *msg,
|
||||
size_t msg_len, size_t digest_len)
|
||||
{
|
||||
unsigned char digest[128];
|
||||
|
||||
fx_hash_ctx ctx;
|
||||
if (!FX_OK(fx_hash_ctx_init(&ctx, func))) {
|
||||
printf("fx_hash_ctx_init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FX_OK(fx_hash_ctx_update(&ctx, msg, msg_len))) {
|
||||
printf("fx_hash_ctx_update failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FX_OK(fx_hash_ctx_finish(&ctx, digest, sizeof digest))) {
|
||||
printf("fx_hash_ctx_finish failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char digest_str[256];
|
||||
for (size_t i = 0; i < digest_len; i++) {
|
||||
snprintf(
|
||||
digest_str + (i * 2), sizeof digest_str - (i * 2),
|
||||
"%02x", digest[i]);
|
||||
}
|
||||
|
||||
printf("%s(%s) = %s\n", func_name, msg, digest_str);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
const char *msg = "Hello, world!";
|
||||
size_t msg_len = strlen(msg);
|
||||
|
||||
print_digest("MD4", FX_HASH_MD4, msg, msg_len, FX_DIGEST_LENGTH_MD4);
|
||||
print_digest("MD5", FX_HASH_MD5, msg, msg_len, FX_DIGEST_LENGTH_MD5);
|
||||
print_digest("SHA1", FX_HASH_SHA1, msg, msg_len, FX_DIGEST_LENGTH_SHA1);
|
||||
print_digest(
|
||||
"SHA224", FX_HASH_SHA2_224, msg, msg_len, FX_DIGEST_LENGTH_SHA2_224);
|
||||
print_digest(
|
||||
"SHA256", FX_HASH_SHA2_256, msg, msg_len, FX_DIGEST_LENGTH_SHA2_256);
|
||||
print_digest(
|
||||
"SHA384", FX_HASH_SHA2_384, msg, msg_len, FX_DIGEST_LENGTH_SHA2_384);
|
||||
print_digest(
|
||||
"SHA512", FX_HASH_SHA2_512, msg, msg_len, FX_DIGEST_LENGTH_SHA2_512);
|
||||
print_digest(
|
||||
"SHA3-224", FX_HASH_SHA3_224, msg, msg_len,
|
||||
FX_DIGEST_LENGTH_SHA3_224);
|
||||
print_digest(
|
||||
"SHA3-256", FX_HASH_SHA3_256, msg, msg_len,
|
||||
FX_DIGEST_LENGTH_SHA3_256);
|
||||
print_digest(
|
||||
"SHA3-384", FX_HASH_SHA3_384, msg, msg_len,
|
||||
FX_DIGEST_LENGTH_SHA3_384);
|
||||
print_digest(
|
||||
"SHA3-512", FX_HASH_SHA3_512, msg, msg_len,
|
||||
FX_DIGEST_LENGTH_SHA3_512);
|
||||
print_digest(
|
||||
"SHAKE128", FX_HASH_SHAKE128, msg, msg_len,
|
||||
FX_DIGEST_LENGTH_SHAKE128);
|
||||
print_digest(
|
||||
"SHAKE256", FX_HASH_SHAKE256, msg, msg_len,
|
||||
FX_DIGEST_LENGTH_SHAKE256);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#include <fx/core/random.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NRAND_NUMBERS 12
|
||||
#define NRAND_BYTES 128
|
||||
#define NRAND_DOUBLES 8
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_random_ctx random;
|
||||
fx_random_init(&random, FX_RANDOM_SECURE | FX_RANDOM_MT19937);
|
||||
|
||||
printf("generating %d random numbers:\n", NRAND_NUMBERS);
|
||||
for (int i = 0; i < NRAND_NUMBERS; i++) {
|
||||
unsigned long long v = fx_random_next_int64(&random);
|
||||
printf(" %llu\n", v);
|
||||
}
|
||||
|
||||
printf("\ngenerating %d random bytes:", NRAND_BYTES);
|
||||
unsigned char bytes[16];
|
||||
for (int i = 0; i < NRAND_BYTES; i++) {
|
||||
if (i == 0 || (i % 16) == 0) {
|
||||
printf("\n ");
|
||||
fx_random_next_bytes(&random, bytes, sizeof bytes);
|
||||
} else if ((i % 4) == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("%02x", bytes[i % 16]);
|
||||
}
|
||||
|
||||
printf("\n\ngenerating %d random doubles:\n", NRAND_DOUBLES);
|
||||
for (int i = 0; i < NRAND_DOUBLES; i++) {
|
||||
double v = fx_random_next_double(&random);
|
||||
printf(" %lf\n", v);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <fx/core/ringbuffer.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUF_SIZE 32
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_ringbuffer *buf = fx_ringbuffer_create(BUF_SIZE);
|
||||
|
||||
size_t read_available = fx_ringbuffer_available_data_remaining(buf);
|
||||
size_t write_available = fx_ringbuffer_write_capacity_remaining(buf);
|
||||
|
||||
printf("read available: %zu\n", read_available);
|
||||
printf("write available: %zu\n", write_available);
|
||||
|
||||
assert(read_available == 0);
|
||||
assert(write_available == BUF_SIZE - 1);
|
||||
|
||||
const char ch = 'X';
|
||||
printf("putc(%c)\n", ch);
|
||||
|
||||
fx_ringbuffer_putc(buf, ch);
|
||||
read_available = fx_ringbuffer_available_data_remaining(buf);
|
||||
write_available = fx_ringbuffer_write_capacity_remaining(buf);
|
||||
printf("read available: %zu\n", read_available);
|
||||
printf("write available: %zu\n", write_available);
|
||||
assert(read_available == 1);
|
||||
assert(write_available == BUF_SIZE - 2);
|
||||
|
||||
int c = fx_ringbuffer_getc(buf);
|
||||
printf("getc() = %c\n", c);
|
||||
assert(c == ch);
|
||||
|
||||
const char s[]
|
||||
= "A very long string that is designed to overflow the "
|
||||
"ringbuffer";
|
||||
size_t s_len = strlen(s);
|
||||
|
||||
size_t nr_written = 0;
|
||||
printf("write(%s)\n", s);
|
||||
fx_ringbuffer_write(buf, s, s_len, &nr_written);
|
||||
read_available = fx_ringbuffer_available_data_remaining(buf);
|
||||
write_available = fx_ringbuffer_write_capacity_remaining(buf);
|
||||
printf("nr written: %zu\n", nr_written);
|
||||
printf("read available: %zu\n", read_available);
|
||||
printf("write available: %zu\n", write_available);
|
||||
assert(read_available == BUF_SIZE - 1);
|
||||
assert(write_available == 0);
|
||||
|
||||
char data[BUF_SIZE + 32] = {0};
|
||||
size_t nr_read = 0;
|
||||
fx_ringbuffer_read(buf, data, sizeof data, &nr_read);
|
||||
printf("read(%u) = %zu bytes\n", BUF_SIZE + 32, nr_read);
|
||||
printf(" = %s\n", data);
|
||||
read_available = fx_ringbuffer_available_data_remaining(buf);
|
||||
write_available = fx_ringbuffer_write_capacity_remaining(buf);
|
||||
printf("read available: %zu\n", read_available);
|
||||
printf("write available: %zu\n", write_available);
|
||||
assert(read_available == 0);
|
||||
assert(write_available == BUF_SIZE - 1);
|
||||
|
||||
fx_ringbuffer_unref(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
#include <fx/core/rope.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void print_rope(const struct fx_rope *rope, int depth)
|
||||
{
|
||||
for (int i = 0; i < depth; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("[%x:", rope->r_flags);
|
||||
|
||||
(FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_CHAR) && printf(" CHAR");
|
||||
(FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_CSTR) && printf(" CSTR");
|
||||
(FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_CSTR_BORROWED)
|
||||
&& printf(" CSTR_BORROWED");
|
||||
(FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_CSTR_STATIC)
|
||||
&& printf(" CSTR_STATIC");
|
||||
(FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_INT) && printf(" INT");
|
||||
(FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_UINT) && printf(" UINT");
|
||||
(FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_COMPOSITE)
|
||||
&& printf(" COMPOSITE");
|
||||
(rope->r_flags & FX_ROPE_F_MALLOC) && printf(" MALLOC");
|
||||
printf("] ");
|
||||
|
||||
switch (FX_ROPE_TYPE(rope->r_flags)) {
|
||||
case FX_ROPE_F_CHAR:
|
||||
printf("%c", rope->r_v.v_char);
|
||||
break;
|
||||
case FX_ROPE_F_CSTR:
|
||||
case FX_ROPE_F_CSTR_BORROWED:
|
||||
case FX_ROPE_F_CSTR_STATIC:
|
||||
printf("%s", rope->r_v.v_cstr.s);
|
||||
break;
|
||||
case FX_ROPE_F_INT:
|
||||
printf("%" PRIdPTR, rope->r_v.v_int);
|
||||
break;
|
||||
case FX_ROPE_F_UINT:
|
||||
printf("%" PRIuPTR, rope->r_v.v_uint);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (FX_ROPE_TYPE(rope->r_flags) == FX_ROPE_F_COMPOSITE) {
|
||||
if (rope->r_v.v_composite.r_left) {
|
||||
print_rope(rope->r_v.v_composite.r_left, depth + 1);
|
||||
}
|
||||
|
||||
if (rope->r_v.v_composite.r_right) {
|
||||
print_rope(rope->r_v.v_composite.r_right, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_rope a = FX_ROPE_CHAR('a');
|
||||
fx_rope b = FX_ROPE_CSTR_STATIC("Hello, world!");
|
||||
fx_rope c = FX_ROPE_INT(-4096);
|
||||
fx_rope d = FX_ROPE_UINT(4096);
|
||||
|
||||
fx_rope str;
|
||||
|
||||
const fx_rope *ropes[] = {
|
||||
&a,
|
||||
&b,
|
||||
&c,
|
||||
&d,
|
||||
};
|
||||
|
||||
fx_rope_join(&str, ropes, sizeof ropes / sizeof ropes[0]);
|
||||
|
||||
print_rope(&str, 0);
|
||||
|
||||
char cstr[1024];
|
||||
fx_rope_to_cstr(&str, cstr, sizeof cstr);
|
||||
fx_rope_destroy(&str);
|
||||
|
||||
printf("%s\n", cstr);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <fx/core/bstr.h>
|
||||
#include <fx/core/stream.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_stream_read_line_s(fx_stdin, fx_stdout);
|
||||
fx_stream_write_char(fx_stdout, '\n');
|
||||
|
||||
char s[16];
|
||||
fx_bstr str;
|
||||
fx_bstr_begin(&str, s, sizeof s);
|
||||
|
||||
fx_stream_read_line_s(fx_stdin, (fx_stream *)&str);
|
||||
fx_stream_write_char((fx_stream *)&str, '\n');
|
||||
|
||||
const char *e = fx_bstr_end(&str);
|
||||
fputs(e, stdout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <fx/ds/array.h>
|
||||
#include <fx/ds/number.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_array *array = fx_array_create();
|
||||
fx_array_append(array, FX_RV_INT(32));
|
||||
fx_array_append(array, FX_RV_INT(64));
|
||||
fx_array_append(array, FX_RV_INT(128));
|
||||
|
||||
fx_iterator *it = fx_iterator_begin(array);
|
||||
fx_foreach_ptr(fx_object, obj, it)
|
||||
{
|
||||
printf("object %p\n", obj);
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_array_unref(array);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#include <CuTest.h>
|
||||
#include <fx/ds/string.h>
|
||||
|
||||
static void test_string_create(CuTest *tc)
|
||||
{
|
||||
fx_string *str = fx_string_create();
|
||||
|
||||
CuAssertPtrNotNull(tc, str);
|
||||
CuAssertIntEquals(tc, 0, fx_string_get_size(str, FX_STRLEN_NORMAL));
|
||||
CuAssertStrEquals(tc, "", fx_string_get_cstr(str));
|
||||
|
||||
fx_string_unref(str);
|
||||
|
||||
str = fx_string_create_from_c('A', 8);
|
||||
|
||||
CuAssertPtrNotNull(tc, str);
|
||||
CuAssertIntEquals(tc, 8, fx_string_get_size(str, FX_STRLEN_NORMAL));
|
||||
CuAssertStrEquals(tc, "AAAAAAAA", fx_string_get_cstr(str));
|
||||
|
||||
fx_string_unref(str);
|
||||
|
||||
str = fx_string_create_from_cstr("Hello, world!");
|
||||
|
||||
CuAssertPtrNotNull(tc, str);
|
||||
CuAssertIntEquals(tc, 13, fx_string_get_size(str, FX_STRLEN_NORMAL));
|
||||
CuAssertStrEquals(tc, "Hello, world!", fx_string_get_cstr(str));
|
||||
|
||||
fx_string_unref(str);
|
||||
}
|
||||
|
||||
static void test_string_length(CuTest *tc)
|
||||
{
|
||||
const char *cstr = "Hello, \033[91;1mworld!";
|
||||
fx_string *s = fx_string_create_from_cstr(cstr);
|
||||
|
||||
CuAssertIntEquals(tc, 13, fx_string_get_size(s, FX_STRLEN_IGNORE_ESC));
|
||||
CuAssertIntEquals(tc, 20, fx_string_get_size(s, FX_STRLEN_NORMAL));
|
||||
|
||||
fx_string_unref(s);
|
||||
}
|
||||
|
||||
CuSuite *get_all_tests(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
||||
SUITE_ADD_TEST(suite, test_string_create);
|
||||
SUITE_ADD_TEST(suite, test_string_length);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#include <fx/ds/number.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_number *number = fx_number_create_float(6.8);
|
||||
|
||||
printf("number=%zd\n", FX_NUMBER_IVAL(number));
|
||||
fx_number_unref(number);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#include <fx/ds/string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_string *string = FX_CSTR("Hello, world!");
|
||||
printf("string object = ");
|
||||
fx_object_to_string(string, fx_stdout);
|
||||
printf("\n");
|
||||
fx_string_unref(string);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#include <fx/core/stream.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
size_t nr_read = 0;
|
||||
fx_stringstream *dest_stream = fx_stringstream_create();
|
||||
fx_stream_buffer *buf = fx_stream_buffer_create_dynamic(1024);
|
||||
fx_stream_read_all_bytes_s(fx_stdin, dest_stream, buf, &nr_read);
|
||||
|
||||
printf("done. read %zu bytes total.\n", nr_read);
|
||||
printf("%s\n", fx_stringstream_ptr(dest_stream));
|
||||
|
||||
fx_stringstream_unref(dest_stream);
|
||||
fx_stream_buffer_unref(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("-------------\n");
|
||||
fx_string *str = fx_string_create_from_cstr("Hello, world!\n");
|
||||
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_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_get_cstr(str));
|
||||
printf("len:%zu, max:%zu\n", fx_string_get_size(str, FX_STRLEN_NORMAL),
|
||||
fx_string_get_capacity(str));
|
||||
printf("-------------\n");
|
||||
|
||||
fx_string_unref(str);
|
||||
|
||||
fx_stringstream *strv = fx_stringstream_create();
|
||||
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);
|
||||
|
||||
printf("%s\n", s);
|
||||
free(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
#include <fx/core/bst.h>
|
||||
#include <fx/core/iterator.h>
|
||||
#include <fx/ds/dict.h>
|
||||
#include <fx/ds/number.h>
|
||||
#include <fx/ds/tree.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NITEMS 16
|
||||
|
||||
struct tree_item {
|
||||
int value;
|
||||
fx_tree_node node;
|
||||
};
|
||||
|
||||
struct bst_item {
|
||||
int value;
|
||||
fx_bst_node node;
|
||||
};
|
||||
|
||||
FX_BST_DEFINE_SIMPLE_GET(struct bst_item, int, node, value, get_node)
|
||||
FX_BST_DEFINE_SIMPLE_INSERT(struct bst_item, node, value, put_node)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_dict *dict = fx_dict_create();
|
||||
fx_dict_put(dict, "hello", FX_RV_INT(32));
|
||||
fx_dict_put(dict, "world", FX_RV_INT(64));
|
||||
fx_dict_put(dict, "more", FX_RV_INT(128));
|
||||
fx_dict_put(dict, "other", FX_RV_INT(256));
|
||||
|
||||
fx_iterator *it = fx_iterator_begin(dict);
|
||||
|
||||
size_t i = 0;
|
||||
fx_foreach(fx_dict_item *, item, it)
|
||||
{
|
||||
printf("item %zu: %s=%d\n", i++, fx_string_get_cstr(item->key),
|
||||
fx_number_get_int(item->value));
|
||||
}
|
||||
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_tree *tree = fx_tree_create();
|
||||
struct tree_item items2[NITEMS];
|
||||
|
||||
for (int i = 0; i < NITEMS; i++) {
|
||||
items2[i].value = i;
|
||||
items2[i].node = FX_TREE_NODE_INIT;
|
||||
}
|
||||
|
||||
fx_tree_set_root(tree, &items2[0].node);
|
||||
|
||||
fx_tree_node_add_child(&items2[0].node, &items2[1].node);
|
||||
fx_tree_node_add_child(&items2[0].node, &items2[2].node);
|
||||
fx_tree_node_add_child(&items2[0].node, &items2[3].node);
|
||||
fx_tree_node_add_child(&items2[0].node, &items2[7].node);
|
||||
fx_tree_node_add_child(&items2[1].node, &items2[4].node);
|
||||
fx_tree_node_add_child(&items2[1].node, &items2[5].node);
|
||||
fx_tree_node_add_child(&items2[4].node, &items2[6].node);
|
||||
|
||||
#if 0
|
||||
it = fx_iterator_begin(tree);
|
||||
fx_tree_iterator it2;
|
||||
fx_tree_foreach(&it2, tree)
|
||||
{
|
||||
struct tree_item *item = fx_unbox(struct tree_item, it2.node, node);
|
||||
|
||||
for (size_t i = 0; i < it2.depth; i++) {
|
||||
fputs(" ", stdout);
|
||||
}
|
||||
|
||||
printf("%u\n", item->value);
|
||||
}
|
||||
|
||||
fx_bst bst = {0};
|
||||
struct bst_item items3[NITEMS] = {0};
|
||||
for (int i = 0; i < NITEMS; i++) {
|
||||
items3[i].value = i;
|
||||
put_node(&bst, &items3[i]);
|
||||
}
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
fx_bst_iterator it3;
|
||||
fx_bst_foreach (&it3, &bst) {
|
||||
struct bst_item *item
|
||||
= fx_unbox(struct bst_item, it3.node, node);
|
||||
|
||||
for (size_t i = 0; i < it3.depth; i++) {
|
||||
fputs(" ", stdout);
|
||||
}
|
||||
|
||||
printf("%d\n", item->value);
|
||||
}
|
||||
|
||||
fx_bst_iterator_begin(&bst, &it3);
|
||||
while (fx_bst_iterator_is_valid(&it3)) {
|
||||
struct bst_item *item
|
||||
= fx_unbox(struct bst_item, it3.node, node);
|
||||
|
||||
if (item->value == 9) {
|
||||
fx_bst_iterator_erase(&it3);
|
||||
} else {
|
||||
fx_bst_iterator_next(&it3);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
fx_bst_foreach (&it3, &bst) {
|
||||
struct bst_item *item
|
||||
= fx_unbox(struct bst_item, it3.node, node);
|
||||
|
||||
for (size_t i = 0; i < it3.depth; i++) {
|
||||
fputs(" ", stdout);
|
||||
}
|
||||
|
||||
printf("%d\n", item->value);
|
||||
}
|
||||
|
||||
fx_tree_unref(tree);
|
||||
#endif
|
||||
fx_dict_unref(dict);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("здравс\u26A0твуите\n");
|
||||
fx_string *str = fx_string_create_from_cstr("здравствуите");
|
||||
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));
|
||||
|
||||
const char *delims[] = {"в"};
|
||||
size_t nr_delims = sizeof delims / sizeof delims[0];
|
||||
|
||||
fx_iterator *it = fx_string_tokenise(str, delims, nr_delims, 0);
|
||||
fx_foreach(const char *, tok, it)
|
||||
{
|
||||
printf("%s\n", tok);
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
fx_string_unref(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#include <fx/ds/uuid.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_uuid *uuid = fx_uuid_create_from_cstr(
|
||||
"5b80ad1f-367f-4a1f-88f3-b3a6f8d1f63d");
|
||||
char str[FX_UUID_STRING_MAX];
|
||||
fx_uuid_to_cstr(uuid, str);
|
||||
printf("%s\n", str);
|
||||
|
||||
fx_uuid_unref(uuid);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/value.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
fx_value_type arg_types[] = {
|
||||
FX_VALUE_TYPE_CSTR,
|
||||
};
|
||||
|
||||
fx_function *func = fx_function_create(
|
||||
"test_function",
|
||||
FX_FUNCTION_F_VARARG,
|
||||
(fx_function_impl)printf,
|
||||
arg_types,
|
||||
1,
|
||||
FX_VALUE_TYPE_INT);
|
||||
|
||||
fx_value args[] = {
|
||||
FX_VALUE_CSTR("Hello %s! You are number %lf\n"),
|
||||
FX_VALUE_CSTR("Jonh"),
|
||||
FX_VALUE_DOUBLE(2.5),
|
||||
};
|
||||
|
||||
fx_value result = FX_VALUE_EMPTY;
|
||||
int r = fx_function_invoke(func, args, 3, &result);
|
||||
printf("%" PRIdPTR "\n", result.v_int);
|
||||
return 0;
|
||||
}
|
||||
+42
-14
@@ -1,22 +1,50 @@
|
||||
#include <dlfcn.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/value.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static double test_function(int a, double b, int c, ...)
|
||||
{
|
||||
#if 1
|
||||
va_list args;
|
||||
va_start(args, c);
|
||||
int d = va_arg(args, int);
|
||||
double e = va_arg(args, double);
|
||||
int f = va_arg(args, int);
|
||||
printf("a=%d, b=%lf, c=%d, d=%d, e=%lf, f=%d\n", a, b, c, d, e, f);
|
||||
return (a + b + c + d + e + f) + 0.5;
|
||||
#else
|
||||
printf("a=%d, b=%lf, c=%d\n", a, b, c);
|
||||
return 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
printf("dynamic loader\n");
|
||||
void *assembly = dlopen(argv[1], RTLD_LAZY);
|
||||
if (!assembly) {
|
||||
printf("cannot load %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
fx_value_type arg_types[] = {
|
||||
FX_VALUE_TYPE_INT,
|
||||
FX_VALUE_TYPE_DOUBLE,
|
||||
FX_VALUE_TYPE_INT,
|
||||
};
|
||||
|
||||
const void *(*asm_info)(void) = dlsym(assembly, "__fx_assembly_get");
|
||||
if (!asm_info) {
|
||||
printf("cannot find assembly info for %s", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
fx_function *func = fx_function_create(
|
||||
"test_function",
|
||||
FX_FUNCTION_F_VARARG,
|
||||
(fx_function_impl)test_function,
|
||||
arg_types,
|
||||
3,
|
||||
FX_VALUE_TYPE_DOUBLE);
|
||||
|
||||
asm_info();
|
||||
printf("OK\n");
|
||||
fx_value args[] = {
|
||||
FX_VALUE_INT(1),
|
||||
FX_VALUE_DOUBLE(2.5),
|
||||
FX_VALUE_INT(3),
|
||||
FX_VALUE_INT(4),
|
||||
FX_VALUE_DOUBLE(5.5),
|
||||
FX_VALUE_INT(6),
|
||||
};
|
||||
|
||||
fx_value result = FX_VALUE_EMPTY;
|
||||
int r = fx_function_invoke(func, args, 6, &result);
|
||||
printf("%lf\n", result.v_double);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static double another_function(int a, double b, int c)
|
||||
{
|
||||
printf("a=%d, b=%lf, c=%d\n", a, b, c);
|
||||
return 1.2;
|
||||
}
|
||||
|
||||
static int test_function(int a, int b, int c, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, c);
|
||||
int d = va_arg(args, int);
|
||||
int e = va_arg(args, int);
|
||||
int f = va_arg(args, int);
|
||||
int g = va_arg(args, int);
|
||||
int h = va_arg(args, int);
|
||||
int i = va_arg(args, int);
|
||||
int j = va_arg(args, int);
|
||||
printf("a=%d, b=%d, c=%d, d=%d, e=%d, f=%d, g=%d, h=%d, i=%d, j=%d\n",
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e,
|
||||
f,
|
||||
g,
|
||||
h,
|
||||
i,
|
||||
j);
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||
another_function(1, 2.5, 5);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#include <CuTest.h>
|
||||
#include <fx/core/stringstream.h>
|
||||
#include <fx/io/path.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void test_path_1(CuTest *tc)
|
||||
{
|
||||
fx_path *path = fx_path_create_from_cstr("C:\\hello\\world\\");
|
||||
char buf[512];
|
||||
fx_stringstream *str = fx_stringstream_create_with_buffer(buf, sizeof buf);
|
||||
|
||||
fx_object_to_string(path, str);
|
||||
|
||||
printf("%s\n", buf);
|
||||
|
||||
fx_path *path2 = fx_path_create_from_cstr("path1\\path2\\");
|
||||
fx_path *path3 = fx_path_create_from_cstr("path3\\path4\\");
|
||||
|
||||
const fx_path *paths[] = {path, path2, path3};
|
||||
|
||||
fx_path *path4 = fx_path_join(paths, sizeof paths / sizeof paths[0]);
|
||||
|
||||
fx_stringstream_reset_with_buffer(str, buf, sizeof buf);
|
||||
fx_object_to_string(path4, str);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
CuSuite *get_all_tests(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
||||
SUITE_ADD_TEST(suite, test_path_1);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#include <fx/io/directory.h>
|
||||
#include <fx/io/path.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *path = argv[1];
|
||||
|
||||
fx_directory *dir;
|
||||
fx_result result = fx_directory_open(
|
||||
NULL, FX_RV_PATH(path), FX_DIRECTORY_OPEN_CREATE_INTERMEDIATE, &dir);
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_directory_unref(dir);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#include <fx/io/directory.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *path = argv[1];
|
||||
|
||||
fx_directory *dir;
|
||||
fx_result result = fx_directory_open(NULL, FX_RV_PATH(path), 0, &dir);
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = fx_directory_delete(dir);
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#include <fx/core/stream.h>
|
||||
#include <fx/io/file.h>
|
||||
#include <fx/io/path.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
fx_file *dest;
|
||||
fx_path *path = fx_path_create_from_cstr("data.txt");
|
||||
fx_result result = fx_file_open(
|
||||
NULL, path, FX_FILE_WRITE_ONLY | FX_FILE_CREATE, &dest);
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t nr_read = 0;
|
||||
fx_stream_buffer *buf = fx_stream_buffer_create_dynamic(1024);
|
||||
fx_stream_read_all_bytes_s(fx_stdin, dest, buf, &nr_read);
|
||||
|
||||
printf("done. read %zu bytes total.\n", nr_read);
|
||||
|
||||
fx_path_unref(path);
|
||||
fx_file_unref(dest);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#include <fx/io/directory.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NRAND_NUMBERS 12
|
||||
#define NRAND_BYTES 128
|
||||
#define NRAND_DOUBLES 8
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_directory *dir = NULL;
|
||||
fx_path *path = fx_path_create_from_cstr(argv[1]);
|
||||
fx_result result = fx_directory_open(FX_DIRECTORY_ROOT, path, 0, &dir);
|
||||
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_throw(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_iterator *it = fx_directory_begin(dir, FX_DIRECTORY_ITERATE_PARENT_FIRST);
|
||||
fx_foreach(fx_directory_entry *, entry, it)
|
||||
{
|
||||
printf("%s\n", fx_path_ptr(entry->filepath));
|
||||
}
|
||||
|
||||
fx_iterator_unref(it);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#include <fx/core/stream.h>
|
||||
#include <fx/ds/array.h>
|
||||
#include <fx/ds/dict.h>
|
||||
#include <fx/ds/number.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/serial.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_serial_ctx *ctx = fx_toml_serial_ctx_create();
|
||||
|
||||
fx_dict *dict = fx_dict_create();
|
||||
|
||||
fx_array *array = fx_array_create();
|
||||
fx_array_append(array, FX_RV_INT(32));
|
||||
fx_array_append(array, FX_RV_INT(64));
|
||||
fx_array_append(array, FX_RV_INT(128));
|
||||
|
||||
fx_dict_put(dict, "numbers", FX_RV(array));
|
||||
|
||||
array = fx_array_create();
|
||||
fx_array_append(array, FX_RV_CSTR("hello"));
|
||||
fx_array_append(array, FX_RV_CSTR("world"));
|
||||
|
||||
fx_dict_put(dict, "strings", FX_RV(array));
|
||||
|
||||
fx_object_to_string(dict, fx_stdout);
|
||||
fx_stream_write_char(fx_stdout, '\n');
|
||||
|
||||
fx_serial_ctx_serialise(ctx, dict, fx_stdout, 0);
|
||||
|
||||
fx_dict_unref(dict);
|
||||
fx_serial_ctx_unref(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
#include <fx/ds/array.h>
|
||||
#include <fx/ds/datetime.h>
|
||||
#include <fx/ds/dict.h>
|
||||
#include <fx/ds/number.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <fx/serial.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
void write_tagged_value(fx_object *data);
|
||||
|
||||
void write_raw_string(const fx_string *data)
|
||||
{
|
||||
fx_stream_write_cstr(fx_stdout, "\"", NULL);
|
||||
|
||||
const fx_iterator *it = fx_iterator_cbegin(data);
|
||||
fx_foreach_c(fx_wchar, c, it)
|
||||
{
|
||||
if (c >= 0x10000) {
|
||||
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);
|
||||
} else if (c <= 0x1F || c >= 0x7F) {
|
||||
fx_stream_write_fmt(fx_stdout, NULL, "\\u%04x", c);
|
||||
} else if (c == '\\' || c == '"') {
|
||||
fx_stream_write_fmt(fx_stdout, NULL, "\\%c", c);
|
||||
} else {
|
||||
fx_stream_write_char(fx_stdout, c);
|
||||
}
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_stream_write_cstr(fx_stdout, "\"", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_string(fx_string *data)
|
||||
{
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
"{ \"type\": \"string\", \"value\": ",
|
||||
NULL);
|
||||
|
||||
write_raw_string(data);
|
||||
|
||||
fx_stream_write_cstr(fx_stdout, " }", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_integer(fx_number *data)
|
||||
{
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
"{ \"type\": \"integer\", \"value\": \"",
|
||||
NULL);
|
||||
|
||||
if (fx_number_is_inf_positive(data)) {
|
||||
fx_stream_write_cstr(fx_stdout, "inf", NULL);
|
||||
} else if (fx_number_is_inf_negative(data)) {
|
||||
fx_stream_write_cstr(fx_stdout, "-inf", NULL);
|
||||
} else if (fx_number_is_nan_positive(data)) {
|
||||
fx_stream_write_cstr(fx_stdout, "nan", NULL);
|
||||
} else if (fx_number_is_nan_negative(data)) {
|
||||
fx_stream_write_cstr(fx_stdout, "-nan", NULL);
|
||||
} else {
|
||||
fx_stream_write_fmt(
|
||||
fx_stdout,
|
||||
NULL,
|
||||
"%lld",
|
||||
fx_number_get_longlong(data),
|
||||
NULL);
|
||||
}
|
||||
|
||||
fx_stream_write_cstr(fx_stdout, "\" }", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_float(fx_number *data)
|
||||
{
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
"{ \"type\": \"float\", \"value\": \"",
|
||||
NULL);
|
||||
|
||||
if (fx_number_is_inf_positive(data)) {
|
||||
fx_stream_write_cstr(fx_stdout, "inf", NULL);
|
||||
} else if (fx_number_is_inf_negative(data)) {
|
||||
fx_stream_write_cstr(fx_stdout, "-inf", NULL);
|
||||
} else if (fx_number_is_nan_positive(data)) {
|
||||
fx_stream_write_cstr(fx_stdout, "nan", NULL);
|
||||
} else if (fx_number_is_nan_negative(data)) {
|
||||
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)
|
||||
|| (v >= 1000000000) || (v <= -1000000000)) {
|
||||
fx_stream_write_fmt(fx_stdout, NULL, "%.15e", v, NULL);
|
||||
} else {
|
||||
fx_stream_write_fmt(fx_stdout, NULL, "%.15f", v, 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);
|
||||
}
|
||||
|
||||
void write_tagged_datetime(fx_datetime *data)
|
||||
{
|
||||
bool has_date = fx_datetime_has_date(data);
|
||||
bool has_time = fx_datetime_has_time(data);
|
||||
bool localtime = fx_datetime_is_localtime(data);
|
||||
|
||||
fx_stream_write_cstr(fx_stdout, "{ \"type\": \"", NULL);
|
||||
|
||||
if (has_date && has_time) {
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
localtime ? "datetime-local" : "datetime",
|
||||
NULL);
|
||||
} else if (has_date) {
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
localtime ? "date-local" : "date",
|
||||
NULL);
|
||||
} else if (has_time) {
|
||||
fx_stream_write_cstr(
|
||||
fx_stdout,
|
||||
localtime ? "time-local" : "time",
|
||||
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_cstr(fx_stdout, fx_string_get_cstr(new_data), NULL);
|
||||
|
||||
fx_stream_write_cstr(fx_stdout, "\" }", NULL);
|
||||
|
||||
fx_string_unref(new_data);
|
||||
}
|
||||
|
||||
void write_tagged_dict(fx_dict *data)
|
||||
{
|
||||
fx_stream_write_cstr(fx_stdout, "{ ", NULL);
|
||||
|
||||
int i = 0;
|
||||
|
||||
fx_iterator *it = fx_iterator_begin(data);
|
||||
fx_foreach(fx_dict_item *, item, it)
|
||||
{
|
||||
if (i++ > 0) {
|
||||
fx_stream_write_cstr(fx_stdout, ", ", NULL);
|
||||
}
|
||||
|
||||
write_raw_string(item->key);
|
||||
fx_stream_write_cstr(fx_stdout, ": ", NULL);
|
||||
write_tagged_value(item->value);
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_stream_write_cstr(fx_stdout, " }", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_array(fx_array *data)
|
||||
{
|
||||
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_cstr(fx_stdout, ", ", NULL);
|
||||
}
|
||||
|
||||
write_tagged_value(obj);
|
||||
}
|
||||
fx_iterator_unref(it);
|
||||
|
||||
fx_stream_write_cstr(fx_stdout, " ]", NULL);
|
||||
}
|
||||
|
||||
void write_tagged_value(fx_object *data)
|
||||
{
|
||||
if (fx_object_is_type(data, FX_TYPE_DICT)) {
|
||||
write_tagged_dict(data);
|
||||
|
||||
} else if (fx_object_is_type(data, FX_TYPE_ARRAY)) {
|
||||
write_tagged_array(data);
|
||||
|
||||
} else if (fx_object_is_type(data, FX_TYPE_STRING)) {
|
||||
write_tagged_string(data);
|
||||
|
||||
} else if (fx_object_is_type(data, FX_TYPE_DATETIME)) {
|
||||
write_tagged_datetime(data);
|
||||
|
||||
} else if (fx_object_is_type(data, FX_TYPE_NUMBER)) {
|
||||
switch (fx_number_get_number_type(data)) {
|
||||
case FX_NUMBER_LONGLONG:
|
||||
write_tagged_integer(data);
|
||||
break;
|
||||
case FX_NUMBER_INT8:
|
||||
write_tagged_bool(data);
|
||||
break;
|
||||
case FX_NUMBER_DOUBLE:
|
||||
write_tagged_float(data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_stream *src = fx_stdin;
|
||||
fx_stream *dest = fx_stdout;
|
||||
|
||||
fx_serial_ctx *ctx = fx_toml_serial_ctx_create();
|
||||
|
||||
fx_object *data;
|
||||
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);
|
||||
|
||||
fx_stream_write_char(fx_stdout, '\n');
|
||||
|
||||
fx_serial_ctx_unref(ctx);
|
||||
fx_object_unref(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#include <fx/serial.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_stream *src = fx_stdin;
|
||||
fx_stream *dest = fx_stdout;
|
||||
|
||||
#if 0
|
||||
fx_serial_ctx *ctx;
|
||||
fx_serial_ctx_create(&ctx);
|
||||
|
||||
fx_object *data;
|
||||
fx_status status = fx_serial_ctx_deserialise(
|
||||
ctx, FX_SERIAL_FORMAT_JSON, src, &data, 0);
|
||||
if (!FX_OK(status)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fx_to_string(FX_OBJECT(data), dest);
|
||||
fx_stream_write_char(fx_stdout, '\n');
|
||||
|
||||
fx_release(data);
|
||||
fx_serial_ctx_destroy(ctx);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
#include <fx/core/error.h>
|
||||
#include <fx/term/print.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum sample_code {
|
||||
SAMPLE_OK = 0,
|
||||
SAMPLE_ERR_IO_FAILURE,
|
||||
SAMPLE_ERR_FILE_READ_FAILED,
|
||||
};
|
||||
|
||||
enum sample_msg {
|
||||
SAMPLE_MSG_SUCCESS = 0,
|
||||
SAMPLE_MSG_A_TEMPLATED_MSG,
|
||||
};
|
||||
|
||||
static const fx_error_definition sample_errors[] = {
|
||||
FX_ERROR_DEFINITION(SAMPLE_OK, "OK", "Success"),
|
||||
FX_ERROR_DEFINITION(SAMPLE_ERR_IO_FAILURE, "IO_FAILURE", "I/O failure"),
|
||||
FX_ERROR_DEFINITION_TEMPLATE(
|
||||
SAMPLE_ERR_FILE_READ_FAILED, "FILE_READ_FAILED",
|
||||
"Failed to read file @i[filepath]",
|
||||
FX_ERROR_TEMPLATE_PARAM(
|
||||
"filepath", FX_ERROR_TEMPLATE_PARAM_STRING, "%s")),
|
||||
};
|
||||
|
||||
static const fx_error_msg sample_error_msg[] = {
|
||||
FX_ERROR_MSG_TEMPLATE(
|
||||
SAMPLE_MSG_A_TEMPLATED_MSG, "A templated message: @e[param1]",
|
||||
FX_ERROR_TEMPLATE_PARAM(
|
||||
"param1", FX_ERROR_TEMPLATE_PARAM_STRING, "%s")),
|
||||
};
|
||||
|
||||
static const char *sample_code_to_string(
|
||||
const struct fx_error_vendor *vendor, fx_error_status_code code)
|
||||
{
|
||||
switch (code) {
|
||||
case SAMPLE_OK:
|
||||
return "OK";
|
||||
case SAMPLE_ERR_IO_FAILURE:
|
||||
return "IO_FAILURE";
|
||||
case SAMPLE_ERR_FILE_READ_FAILED:
|
||||
return "FILE_READ_FAILED";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static fx_error_vendor sample_vendor = {
|
||||
.v_name = "Sample",
|
||||
.v_error_definitions = sample_errors,
|
||||
.v_error_definitions_length = sizeof sample_errors,
|
||||
.v_msg = sample_error_msg,
|
||||
.v_msg_length = sizeof sample_error_msg,
|
||||
};
|
||||
|
||||
static fx_result error_return_3(void)
|
||||
{
|
||||
fx_result err = fx_error_with_string(
|
||||
&sample_vendor, SAMPLE_ERR_IO_FAILURE,
|
||||
"I/O failure while reading file");
|
||||
|
||||
fx_error_add_submsg_string(
|
||||
err, FX_ERROR_SUBMSG_ERROR, "An @e{error} message");
|
||||
fx_error_add_submsg_string(
|
||||
err, FX_ERROR_SUBMSG_WARNING, "A @w{warning} message");
|
||||
fx_error_add_submsg_template(
|
||||
err, FX_ERROR_SUBMSG_WARNING, SAMPLE_MSG_A_TEMPLATED_MSG,
|
||||
FX_ERROR_PARAM("param1", "Hello!"));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static fx_result error_return_2(void)
|
||||
{
|
||||
return fx_result_propagate(error_return_3());
|
||||
}
|
||||
|
||||
static fx_result error_return_1(void)
|
||||
{
|
||||
return fx_result_propagate(error_return_2());
|
||||
}
|
||||
|
||||
struct param {
|
||||
const char *name;
|
||||
int value;
|
||||
};
|
||||
|
||||
#define PARAM(n, v) \
|
||||
(struct param) \
|
||||
{ \
|
||||
.name = (n), .value = (v) \
|
||||
}
|
||||
|
||||
static void __test(struct param params[])
|
||||
{
|
||||
for (size_t i = 0; params[i].name; i++) {
|
||||
printf("%s = %d\n", params[i].name, params[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
#define test(...) __test((struct param[]) {__VA_ARGS__, {}})
|
||||
|
||||
static fx_result some_operation(void)
|
||||
{
|
||||
fx_result result = error_return_2();
|
||||
if (fx_result_is_error(result)) {
|
||||
fx_result err = fx_error_with_template(
|
||||
&sample_vendor, SAMPLE_ERR_FILE_READ_FAILED,
|
||||
FX_ERROR_PARAM("filepath", "src/Manifest.json"));
|
||||
fx_error_add_submsg_string(
|
||||
err, FX_ERROR_SUBMSG_INFO,
|
||||
"An @i{informational} message");
|
||||
|
||||
fx_error_caused_by_fx_status(result, FX_ERR_IO_FAILURE);
|
||||
fx_result err2 = fx_error_caused_by(err, result);
|
||||
|
||||
return err2;
|
||||
}
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fx_set_error_report_function(fx_enhanced_error_reporter, FX_ERROR_REPORT_ALL);
|
||||
|
||||
test(PARAM("Hello", 1), PARAM("Goodbye", 2));
|
||||
|
||||
fx_result err;
|
||||
if (FX_CATCH(err, some_operation())) {
|
||||
fx_throw(err);
|
||||
}
|
||||
|
||||
fx_throw_status(FX_ERR_INVALID_ARGUMENT);
|
||||
fx_throw_status_string(FX_ERR_INVALID_ARGUMENT, "Hello!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
#include <fx/term/tty.h>
|
||||
#include <fx/term/print.h>
|
||||
#include <fx/ds/string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define F_GREEN "[green]"
|
||||
#define F_YELLOW "[yellow]"
|
||||
#define F_RESET "[reset]"
|
||||
|
||||
static const char *text = F_YELLOW
|
||||
"But I must " F_GREEN "explain " F_YELLOW "to you " F_GREEN
|
||||
"how all this " F_YELLOW "mistaken idea of" F_RESET
|
||||
" denouncing pleasure " F_GREEN "and praising pain was born " F_YELLOW
|
||||
"and I will give you " F_RESET "a complete account of " F_YELLOW
|
||||
"the system, and " F_RESET
|
||||
"expound the actual teachings of the great explorer of the truth, the "
|
||||
"master-builder of human happiness.\n"
|
||||
"No one rejects, dislikes, or avoids pleasure itself, because it is "
|
||||
"pleasure, but because those who do not know how to pursue pleasure "
|
||||
"rationally encounter consequences that are extremely painful. Nor "
|
||||
"again is there anyone who loves or pursues or desires to obtain pain "
|
||||
"of itself, because it is pain, but because occasionally circumstances "
|
||||
"occur in which toil and pain can procure him some great pleasure.\n"
|
||||
"To take a trivial example, which of us ever undertakes laborious "
|
||||
"physical exercise, except to obtain some advantage from it? But who "
|
||||
"has any right to find fault with a man who chooses to enjoy a "
|
||||
"pleasure that has no annoying consequences, or one who avoids a pain "
|
||||
"that produces no resultant pleasure? On the other hand, we denounce "
|
||||
"with righteous indignation and dislike men who are so beguiled and "
|
||||
"demoralized by the charms of pleasure of the moment, so blinded by "
|
||||
"desire, that they cannot foresee.";
|
||||
|
||||
static const char *text2
|
||||
= "But I must explain to you how all this mistaken idea of denouncing "
|
||||
"pleasure and praising pain was born and I will give you a complete "
|
||||
"account of the system, and expound the actual teachings of the "
|
||||
"great explorer of the truth, the master-builder of human "
|
||||
"happiness.\n"
|
||||
"No one rejects, dislikes, or avoids pleasure itself, because it is "
|
||||
"pleasure, but because those who do not know how to pursue pleasure "
|
||||
"rationally encounter consequences that are extremely painful. Nor "
|
||||
"again is there anyone who loves or pursues or desires to obtain "
|
||||
"pain of itself, because it is pain, but because occasionally "
|
||||
"circumstances occur in which toil and pain can procure him some "
|
||||
"great pleasure.\n"
|
||||
"To take a trivial example, which of us ever undertakes laborious "
|
||||
"physical exercise, except to obtain some advantage from it? But who "
|
||||
"has any right to find fault with a man who chooses to enjoy a "
|
||||
"pleasure that has no annoying consequences, or one who avoids a "
|
||||
"pain that produces no resultant pleasure? On the other hand, we "
|
||||
"denounce with righteous indignation and dislike men who are so "
|
||||
"beguiled and demoralized by the charms of pleasure of the moment, "
|
||||
"so blinded by desire, that they cannot foresee.";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const char *s = "[magenta,uline]Hello, [bright_magenta]world![reset]";
|
||||
fx_puts(s);
|
||||
fx_putc('\n');
|
||||
|
||||
fx_string *str = fx_string_create_from_cstr(s);
|
||||
size_t len = fx_string_get_size(str, FX_STRLEN_IGNORE_MOD);
|
||||
printf("length = %zu\n", len);
|
||||
|
||||
fx_paragraph_format format = { 0 };
|
||||
format.p_left_margin = 5;
|
||||
format.p_right_margin = 5;
|
||||
format.p_flags = FX_PARAGRAPH_DOUBLE_LINE_BREAK;
|
||||
|
||||
fx_print_paragraph(text, fx_stdtty, &format);
|
||||
|
||||
fx_i("An informational message\n\nWith multiple lines");
|
||||
fx_warn("A warning message\nWith multiple lines");
|
||||
fx_err("An error message\nWith multiple lines");
|
||||
|
||||
fx_printf("[red]formatting ignored: '%s'[reset]\n[dark_grey]dark text[reset]\n", "[blue]wow![reset]");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user