Hash :
3bfc1bc1
Author :
Date :
2025-05-12T18:52:05
misc: Ensure proper type for darray size
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
/*
* Copyright © 2024 Pierre Le Marre <dev@wismill.eu>
* SPDX-License-Identifier: MIT
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include "src/darray.h"
#include "src/utils.h"
#include "test/utils-text.h"
/* For each line, drop substring starting from a given needle, then drop
* the line if the rest are only whitespaces. The needle must not contain
* "\n". */
char *
strip_lines(const char *input, size_t input_length, const char *prefix)
{
darray_char buf = darray_new();
const size_t prefix_len = strlen(prefix);
const char *start = input;
const char *end = input + input_length;
const char *next = strstr(start, prefix);
size_t count;
while (start < end && next != NULL) {
count = (size_t)(next - start);
next = start + count + prefix_len;
/* Find previous non-space */
size_t i;
for (i = count; i > 0; i--) {
if (start[i - 1] != ' ' && start[i - 1] != '\t')
break;
}
bool dropped = false;
/* Drop line if only whitespaces */
if (i == 0 || start[i - 1] == '\n') {
count = i;
dropped = true;
}
/* Append string */
darray_append_items(buf, start, (darray_size_t) count);
/* Find end of line */
if (next >= end) {
start = end;
break;
}
start = strchr(next, 0x0a);
if (start == NULL) {
start = end;
break;
}
if (dropped)
start++;
next = strstr(start, prefix);
}
/* Append remaining */
if (start < end) {
count = (size_t)(end - start);
darray_append_items(buf, start, (darray_size_t) count);
}
darray_append(buf, '\0');
return buf.item;
}
char *
uncomment(const char *input, size_t input_length, const char *prefix)
{
darray_char buf = darray_new();
const size_t prefix_len = strlen(prefix);
const char *start = input;
const char *end = input + input_length;
char *next = strstr(start, prefix);
size_t count;
while (start < end && next != NULL) {
count = (size_t)(next - start);
darray_append_items(buf, start, (darray_size_t) count);
/* Skip prefix */
start += count + prefix_len;
/* Find end of line */
if (start >= end)
break;
next = strchr(start, 0x0a);
if (next == NULL)
break;
next = strstr(next, prefix);
}
/* Append remaining */
if (start < end) {
count = (size_t)(end - start);
darray_append_items(buf, start, (darray_size_t) count);
}
darray_append(buf, '\0');
return buf.item;
}
/* Split string into lines */
size_t
split_lines(const char *input, size_t input_length,
struct text_line *output, size_t output_length)
{
const char *start = input;
char *next;
size_t l;
size_t i = 0;
for (l = 0; i < input_length && l < output_length && *start != '\0'; l++) {
/* Look for newline character */
next = strchr(start, 0x0a);
output[l].start = start;
if (next == NULL) {
/* Not found: add the rest of the string */
output[l++].length = strlen(start);
break;
}
output[l].length = (size_t)(next - start) + 1;
start = next + 1;
i += output[l].length;
}
return l;
}
size_t
concat_lines(struct text_line *lines, size_t length,
const char *sep, char *output)
{
char *out = output;
size_t sep_len = strlen(sep);
for (size_t i = 0; i < length; i++) {
if (i > 0) {
memcpy(out, sep, sep_len);
out += sep_len;
}
memcpy(out, lines[i].start, lines[i].length);
out += lines[i].length;
}
*out = '\0';
return (size_t)(out - output);
}
size_t
shuffle_lines(struct text_line *lines, size_t length, char *output)
{
/* Shuffle lines in-place using Fisher–Yates algorithm.
* See: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle */
assert(length < RAND_MAX);
char *out = output;
if (length > 1) {
/* 1. Set the current i to the last line.
* 2. Take a random line j before the current line i.
* 3. Swap the lines i and j.
* 4. Append line i to the output.
* 5. If i is the first line, stop. Else decrease i and go to 2).
*/
for (size_t i = length - 1; i > 0; i--) {
/* Swap current line with random line before it */
size_t j = rand() % (i+1);
struct text_line tmp = lines[j];
lines[j] = lines[i];
lines[i] = tmp;
/* Append current line */
memcpy(out, lines[i].start, lines[i].length);
out += lines[i].length;
/* Ensure line ends with newline */
if (out[-1] != '\n') {
out[0] = '\n';
out++;
}
}
}
return (size_t)(out - output);
}