1#include "include/pw.h"
 2#include "src/types/array/array_internal.h"
 3
 4[[nodiscard]] bool pw_dedent(PwValuePtr lines)
 5{
 6    PwValue lines_array = PW_NULL;
 7    PwValuePtr lines_ptr;
 8    if (pw_is_string(lines)) {
 9        if (!pw_string_split_chr(lines, '\n', 0, &lines_array)) {
10            return true;
11        }
12        lines_ptr = &lines_array;
13    } else {
14        pw_assert(pw_is_array(lines));
15        lines_ptr = lines;
16    }
17
18    // dedent in-place, so access items directly to avoid cloning
19    _PwArray* array = _pw_array_noiter_cow(lines_ptr);
20    if (!array) {
21        return false;
22    }
23
24    static char32_t indent_chars[] = {' ', '\t', 0};
25
26    unsigned n = pw_array_length(lines_ptr);
27
28    unsigned indent[n];
29
30    // measure indents
31    unsigned min_indent = UINT_MAX;
32    for (unsigned i = 0; i < n; i++) {
33        PwValuePtr line = &array->items[i];
34        indent[i] = 0;
35        if (pw_is_string(line)) {
36            indent[i] = pw_string_skip_chars(line, 0, indent_chars);
37            if (indent[i] && indent[i] < min_indent) {
38                min_indent = indent[i];
39            }
40        }
41    }
42    if (min_indent == UINT_MAX) {
43        // nothing to dedent
44        return true;
45    }
46
47    // dedent
48    for (unsigned i = 0; i < n; i++) {
49        if (indent[i]) {
50            PwValuePtr line = &array->items[i];
51            if (!pw_string_erase(line, 0, min_indent)) {
52                return false;
53            }
54        }
55    }
56
57    // pertain the type of result
58    if (pw_is_string(lines)) {
59        if (!pw_array_join(lines_ptr, '\n', lines)) {
60            return false;
61        }
62    }
63    return true;
64}