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}