return p - names;
}
-char **parse_names(char *buf, int size)
+int parse_names(char *buf, int size, char ***out)
{
char **names = NULL;
size_t names_cap = 0;
size_t names_len = 0;
char *p = buf;
char *end = buf + size;
+ int err = 0;
while (p < end) {
char *next = strchr(p, '\n');
- if (next && next < end) {
- *next = 0;
+ if (!next) {
+ err = REFTABLE_FORMAT_ERROR;
+ goto done;
+ } else if (next < end) {
+ *next = '\0';
} else {
next = end;
}
+
if (p < next) {
if (REFTABLE_ALLOC_GROW(names, names_len + 1,
- names_cap))
- goto err;
+ names_cap)) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
names[names_len] = reftable_strdup(p);
- if (!names[names_len++])
- goto err;
+ if (!names[names_len++]) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
}
p = next + 1;
}
- if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap))
- goto err;
+ if (REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap)) {
+ err = REFTABLE_OUT_OF_MEMORY_ERROR;
+ goto done;
+ }
names[names_len] = NULL;
- return names;
-
-err:
+ *out = names;
+ return 0;
+done:
for (size_t i = 0; i < names_len; i++)
reftable_free(names[i]);
reftable_free(names);
- return NULL;
+ return err;
}
int names_equal(const char **a, const char **b)
/*
* Parse a newline separated list of names. `size` is the length of the buffer,
- * without terminating '\0'. Empty names are discarded. Returns a `NULL`
- * pointer when allocations fail.
+ * without terminating '\0'. Empty names are discarded.
+ *
+ * Returns 0 on success, a reftable error code on error.
*/
-char **parse_names(char *buf, int size);
+int parse_names(char *buf, int size, char ***out);
/* compares two NULL-terminated arrays of strings. */
int names_equal(const char **a, const char **b);
}
buf[size] = 0;
- *namesp = parse_names(buf, size);
- if (!*namesp) {
- err = REFTABLE_OUT_OF_MEMORY_ERROR;
- goto done;
- }
-
+ err = parse_names(buf, size, namesp);
done:
reftable_free(buf);
return err;
#include "unit-test.h"
#include "lib-reftable.h"
#include "reftable/basics.h"
+#include "reftable/reftable-error.h"
struct integer_needle_lesseq_args {
int needle;
void test_reftable_basics__parse_names(void)
{
char in1[] = "line\n";
- char in2[] = "a\nb\nc";
- char **out = parse_names(in1, strlen(in1));
+ char in2[] = "a\nb\nc\n";
+ char **out = NULL;
+ int err = parse_names(in1, strlen(in1), &out);
+ cl_assert(err == 0);
cl_assert(out != NULL);
cl_assert_equal_s(out[0], "line");
cl_assert(!out[1]);
free_names(out);
- out = parse_names(in2, strlen(in2));
+ out = NULL;
+ err = parse_names(in2, strlen(in2), &out);
+ cl_assert(err == 0);
cl_assert(out != NULL);
cl_assert_equal_s(out[0], "a");
cl_assert_equal_s(out[1], "b");
free_names(out);
}
+void test_reftable_basics__parse_names_missing_newline(void)
+{
+ char in1[] = "line\nline2";
+ char **out = NULL;
+ int err = parse_names(in1, strlen(in1), &out);
+ cl_assert(err == REFTABLE_FORMAT_ERROR);
+ cl_assert(out == NULL);
+}
+
void test_reftable_basics__parse_names_drop_empty_string(void)
{
char in[] = "a\n\nb\n";
- char **out = parse_names(in, strlen(in));
+ char **out = NULL;
+ int err = parse_names(in, strlen(in), &out);
+ cl_assert(err == 0);
cl_assert(out != NULL);
cl_assert_equal_s(out[0], "a");
/* simply '\n' should be dropped as empty string */