diff --git a/libc3/array.c b/libc3/array.c
index 4a204e6..e12d7f6 100644
--- a/libc3/array.c
+++ b/libc3/array.c
@@ -71,7 +71,8 @@ s_array * array_copy (const s_array *src, s_array *dest)
dest->size = src->size;
dest->type = src->type;
if (src->data) {
- dest->data = calloc(1, src->size);
+ if (! (dest->data = calloc(1, src->size)))
+ errx(1, "array_copy: out of memory");
memcpy(dest->data, src->data, dest->size);
}
else
@@ -190,6 +191,27 @@ s_array * array_init_1 (s_array *array, s8 *p)
return array;
}
+s_str * array_inspect (const s_array *array, s_str *dest)
+{
+ sw size;
+ s_buf tmp;
+ size = buf_inspect_array_size(array);
+ if (size < 0) {
+ assert(! "array_inspect: error");
+ errx(1, "array_inspect: error");
+ return NULL;
+ }
+ buf_init_alloc(&tmp, size);
+ buf_inspect_array(&tmp, array);
+ assert(tmp.wpos == tmp.size);
+ if (tmp.wpos != tmp.size) {
+ buf_clean(&tmp);
+ errx(1, "array_inspect: buf_inspect_array");
+ return NULL;
+ }
+ return buf_to_str(&tmp, dest);
+}
+
uw array_type_size (const s_sym *type)
{
if (type == sym_1("Bool"))
diff --git a/libc3/array.h b/libc3/array.h
index cf33a98..c91970b 100644
--- a/libc3/array.h
+++ b/libc3/array.h
@@ -20,6 +20,7 @@ s_array * array_copy (const s_array *src, s_array *dest);
s_array * array_init (s_array *a, const s_sym *type,
uw dimension, const uw *dimensions);
s_array * array_init_1 (s_array *a, s8 *p);
+s_str * array_inspect (const s_array *array, s_str *dest);
void * array_data (const s_array *a, const uw *address);
s_tag * array_data_tag (s_tag *a, const s_tag *address,
s_tag *dest);
diff --git a/libc3/buf_inspect.c b/libc3/buf_inspect.c
index 3b0c24f..cff786a 100644
--- a/libc3/buf_inspect.c
+++ b/libc3/buf_inspect.c
@@ -28,12 +28,15 @@
sw buf_inspect_array_data (s_buf *buf, const s_array *array);
sw buf_inspect_array_data_rec (s_buf *buf, const s_array *array,
+ const u8 **data, f_buf_inspect inspect,
const s_tag **tag, uw *address,
uw dimension);
sw buf_inspect_array_data_size (const s_array *array);
sw buf_inspect_array_data_size_rec (const s_array *array,
- const s_tag **tag, uw *address,
- uw dimension);
+ const u8 **data,
+ f_buf_inspect_size inspect_size,
+ const s_tag **tag,
+ uw *address, uw dimension);
sw buf_inspect_tag_type (s_buf *buf, e_tag_type type);
sw buf_inspect_array (s_buf *buf, const s_array *array)
@@ -61,19 +64,30 @@ sw buf_inspect_array (s_buf *buf, const s_array *array)
sw buf_inspect_array_data (s_buf *buf, const s_array *array)
{
uw *address;
- s_tag *tag;
+ u8 *data = NULL;
+ f_buf_inspect inspect = NULL;
+ s_tag *tag = NULL;
+ e_tag_type tag_type;
sw r;
assert(buf);
assert(array);
address = calloc(array->dimension, sizeof(uw));
- tag = array->tags;
- r = buf_inspect_array_data_rec(buf, array, (const s_tag **) &tag,
+ if (array->data) {
+ data = array->data;
+ tag_type = array_type_to_tag_type(array->type);
+ inspect = tag_type_to_buf_inspect(tag_type);
+ }
+ else
+ tag = array->tags;
+ r = buf_inspect_array_data_rec(buf, array, (const u8 **) &data,
+ inspect, (const s_tag **) &tag,
address, 0);
free(address);
return r;
}
sw buf_inspect_array_data_rec (s_buf *buf, const s_array *array,
+ const u8 **data, f_buf_inspect inspect,
const s_tag **tag, uw *address,
uw dimension)
{
@@ -85,13 +99,22 @@ sw buf_inspect_array_data_rec (s_buf *buf, const s_array *array,
address[dimension] = 0;
while (1) {
if (dimension == array->dimension - 1) {
- if ((r = buf_inspect_tag(buf, *tag)) <= 0)
- goto clean;
- result += r;
- (*tag)++;
+ if (*data) {
+ if ((r = inspect(buf, *data)) <= 0)
+ goto clean;
+ result += r;
+ *data += array->dimensions[dimension].item_size;
+ }
+ else if (*tag) {
+ if ((r = buf_inspect_tag(buf, *tag)) <= 0)
+ goto clean;
+ result += r;
+ (*tag)++;
+ }
}
else {
- if ((r = buf_inspect_array_data_rec(buf, array, tag, address,
+ if ((r = buf_inspect_array_data_rec(buf, array, data, inspect,
+ tag, address,
dimension + 1)) <= 0)
goto clean;
result += r;
@@ -114,20 +137,33 @@ sw buf_inspect_array_data_rec (s_buf *buf, const s_array *array,
sw buf_inspect_array_data_size (const s_array *array)
{
uw *address;
- s_tag *tag;
+ u8 *data = NULL;
+ f_buf_inspect_size inspect_size = NULL;
+ s_tag *tag = NULL;
+ e_tag_type tag_type;
sw r;
assert(array);
address = calloc(array->dimension, sizeof(uw));
- tag = array->tags;
- r = buf_inspect_array_data_size_rec(array, (const s_tag **) &tag,
+ if (array->data) {
+ data = array->data;
+ tag_type = array_type_to_tag_type(array->type);
+ inspect_size = tag_type_to_buf_inspect_size(tag_type);
+ }
+ else
+ tag = array->tags;
+ r = buf_inspect_array_data_size_rec(array, (const u8 **) &data,
+ inspect_size,
+ (const s_tag **) &tag,
address, 0);
free(address);
return r;
}
sw buf_inspect_array_data_size_rec (const s_array *array,
- const s_tag **tag, uw *address,
- uw dimension)
+ const u8 **data,
+ f_buf_inspect_size inspect_size,
+ const s_tag **tag,
+ uw *address, uw dimension)
{
sw r;
sw result = 0;
@@ -136,13 +172,23 @@ sw buf_inspect_array_data_size_rec (const s_array *array,
address[dimension] = 0;
while (1) {
if (dimension == array->dimension - 1) {
- if ((r = buf_inspect_tag_size(*tag)) <= 0)
- goto clean;
- result += r;
- (*tag)++;
+ if (*data) {
+ if ((r = inspect_size(*data)) <= 0)
+ goto clean;
+ result += r;
+ *data += array->dimensions[dimension].item_size;
+ }
+ else if (*tag) {
+ if ((r = buf_inspect_tag_size(*tag)) <= 0)
+ goto clean;
+ result += r;
+ (*tag)++;
+ }
}
else {
- if ((r = buf_inspect_array_data_size_rec(array, tag, address,
+ if ((r = buf_inspect_array_data_size_rec(array, data,
+ inspect_size,
+ tag, address,
dimension + 1)) <= 0)
goto clean;
result += r;
diff --git a/test/array_test.c b/test/array_test.c
index adf727b..b7c224d 100644
--- a/test/array_test.c
+++ b/test/array_test.c
@@ -12,6 +12,7 @@
*/
#include <string.h>
#include "../libc3/array.h"
+#include "../libc3/str.h"
#include "../libc3/sym.h"
#include "test.h"
@@ -29,16 +30,30 @@
array_clean(&a); \
} while(0)
+#define ARRAY_TEST_INSPECT(test, expected) \
+ do { \
+ s_str str; \
+ s_array tmp; \
+ test_context("array_inspect(" # test ") -> " # expected); \
+ TEST_EQ(array_init_1(&tmp, (test)), &tmp); \
+ TEST_EQ(array_inspect(&tmp, &str), &str); \
+ TEST_STRNCMP(str.ptr.p, (expected), str.size); \
+ array_clean(&tmp); \
+ str_clean(&str); \
+ } while(0)
+
void array_test ();
TEST_CASE_PROTOTYPE(array_data);
TEST_CASE_PROTOTYPE(array_init_clean);
TEST_CASE_PROTOTYPE(array_init_1_clean);
+TEST_CASE_PROTOTYPE(array_inspect);
void array_test ()
{
TEST_CASE_RUN(array_init_clean);
TEST_CASE_RUN(array_init_1_clean);
TEST_CASE_RUN(array_data);
+ TEST_CASE_RUN(array_inspect);
}
TEST_CASE(array_data)
@@ -49,6 +64,11 @@ TEST_CASE(array_data)
TEST_EQ(* (u8 *) array_data(&a, (uw []) {1}), 2);
TEST_EQ(* (u8 *) array_data(&a, (uw []) {2}), 3);
array_clean(&a);
+ TEST_EQ(array_init_1(&a, "(U8) {1 + 1, 2 + 2, 3 + 3}"), &a);
+ TEST_EQ(* (u8 *) array_data(&a, (uw []) {0}), 2);
+ TEST_EQ(* (u8 *) array_data(&a, (uw []) {1}), 4);
+ TEST_EQ(* (u8 *) array_data(&a, (uw []) {2}), 6);
+ array_clean(&a);
}
TEST_CASE_END(array_data)
@@ -77,3 +97,24 @@ TEST_CASE(array_init_1_clean)
ARRAY_TEST_INIT_1_CLEAN("(U8) {{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}");
}
TEST_CASE_END(array_init_1_clean)
+
+TEST_CASE(array_inspect)
+{
+ ARRAY_TEST_INSPECT("(U8) {0}",
+ "(U8) {0}");
+ ARRAY_TEST_INSPECT("(U8) {0, 0}",
+ "(U8) {0, 0}");
+ ARRAY_TEST_INSPECT("(U8) {0, 0, 0}",
+ "(U8) {0, 0, 0}");
+ ARRAY_TEST_INSPECT("(U8) {{0}, {0}}",
+ "(U8) {{0}, {0}}");
+ ARRAY_TEST_INSPECT("(U8) {{0, 0}, {0, 0}}",
+ "(U8) {{0, 0}, {0, 0}}");
+ ARRAY_TEST_INSPECT("(U8) {{0, 0}, {0, 0}, {0, 0}}",
+ "(U8) {{0, 0}, {0, 0}, {0, 0}}");
+ ARRAY_TEST_INSPECT("(U8) {{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}",
+ "(U8) {{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}");
+ ARRAY_TEST_INSPECT("(U8) {1, 2, 3}", "(U8) {1, 2, 3}");
+ ARRAY_TEST_INSPECT("(U8) {1 + 1, 2 + 2, 3 + 3}", "(U8) {2, 4, 6}");
+}
+TEST_CASE_END(array_inspect)