diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-07-13 18:05:14 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-07-13 18:05:14 -0400 |
| commit | f64aaf5960287f776232f909e145ac3f72fec73c (patch) | |
| tree | 1f6d7d36ed58ca4219a1bb89e7f63aeadf8cf0bb /builtins | |
| parent | 445f79cb70e72698283539b65e43fc71a47ad311 (diff) | |
Add array:pairs()
Diffstat (limited to 'builtins')
| -rw-r--r-- | builtins/array.c | 43 | ||||
| -rw-r--r-- | builtins/array.h | 1 |
2 files changed, 44 insertions, 0 deletions
diff --git a/builtins/array.c b/builtins/array.c index 2d45591c..7086ff7f 100644 --- a/builtins/array.c +++ b/builtins/array.c @@ -320,6 +320,49 @@ public array_t Array$reversed(array_t array) return reversed; } +typedef struct { + array_t arr; + int64_t i, j, item_size; + bool self_pairs:1, ordered:1; +} pair_info_t; + +static bool next_pair(void *x, void *y, pair_info_t *info) +{ + if (info->i > info->arr.length || info->j > info->arr.length) + return false; + + memcpy(x, info->arr.data + info->arr.stride * (info->i-1), info->item_size); + memcpy(y, info->arr.data + info->arr.stride * (info->j-1), info->item_size); + info->j += 1; + if (!info->self_pairs && info->j == info->i) + info->j += 1; + + if (info->j > info->arr.length) { + info->i += 1; + if (info->ordered) + info->j = 1; + else if (info->self_pairs) + info->j = info->i; + else + info->j = info->i + 1; + } + return true; +} + +public closure_t Array$pairs(array_t arr, bool self_pairs, bool ordered, const TypeInfo *type) +{ + return (closure_t){ + .fn=next_pair, + .userdata=new(pair_info_t, + .arr=arr, + .i=1, + .j=self_pairs ? 1 : 2, + .item_size=get_item_size(type), + .self_pairs=self_pairs, + .ordered=ordered), + }; +} + public array_t Array$concat(array_t x, array_t y, const TypeInfo *type) { int64_t item_size = get_item_size(type); diff --git a/builtins/array.h b/builtins/array.h index 56794a22..1b7fa4cb 100644 --- a/builtins/array.h +++ b/builtins/array.h @@ -69,6 +69,7 @@ array_t Array$to(array_t *array, int64_t last); array_t Array$by(array_t *array, int64_t stride); array_t Array$reversed(array_t array); array_t Array$concat(array_t x, array_t y, const TypeInfo *type); +closure_t Array$pairs(array_t x, bool self_pairs, bool ordered, const TypeInfo *type); uint32_t Array$hash(const array_t *arr, const TypeInfo *type); int32_t Array$compare(const array_t *x, const array_t *y, const TypeInfo *type); bool Array$equal(const array_t *x, const array_t *y, const TypeInfo *type); |
