// SPDX-License-Identifier: GPL-2.0
/*
 * C++ stream style string builder used in KUnit for building messages.
 *
 * Copyright (C) 2019, Google LLC.
 * Author: Brendan Higgins <brendanhiggins@google.com>
 */

#include <kunit/static_stub.h>
#include <kunit/test.h>
#include <linux/list.h>
#include <linux/seq_buf.h>
#include <linux/slab.h>

#include "string-stream.h"


static struct string_stream_fragment *alloc_string_stream_fragment(int len, gfp_t gfp)
{
	struct string_stream_fragment *frag;

	frag = kzalloc_obj(*frag, gfp);
	if (!frag)
		return ERR_PTR(-ENOMEM);

	frag->fragment = kmalloc(len, gfp);
	if (!frag->fragment) {
		kfree(frag);
		return ERR_PTR(-ENOMEM);
	}

	return frag;
}

static void string_stream_fragment_destroy(struct string_stream_fragment *frag)
{
	list_del(&frag->node);
	kfree(frag->fragment);
	kfree(frag);
}

int string_stream_vadd(struct string_stream *stream,
		       const char *fmt,
		       va_list args)
{
	struct string_stream_fragment *frag_container;
	int buf_len, result_len;
	va_list args_for_counting;

	/* Make a copy because `vsnprintf` could change it */
	va_copy(args_for_counting, args);

	/* Evaluate length of formatted string */
	buf_len = vsnprintf(NULL, 0, fmt, args_for_counting);

	va_end(args_for_counting);

	if (buf_len == 0)
		return 0;

	/* Reserve one extra for possible appended newline. */
	if (stream->append_newlines)
		buf_len++;

	/* Need space for null byte. */
	buf_len++;

	frag_container = alloc_string_stream_fragment(buf_len, stream->gfp);
	if (IS_ERR(frag_container))
		return PTR_ERR(frag_container);

	if (stream->append_newlines) {
		/* Don't include reserved newline byte in writeable length. */
		result_len = vsnprintf(frag_container->fragment, buf_len - 1, fmt, args);

		/* Append newline if necessary. */
		if (frag_container->fragment[result_len - 1] != '\n')
			result_len += strscpy(frag_container->fragment + result_len,
					      "\n", buf_len - result_len);
	} else {
		result_len = vsnprintf(frag_container->fragment, buf_len, fmt, args);
	}

	spin_lock(&stream->lock);
	stream->length += result_len;
	list_add_tail(&frag_container->node, &stream->fragments);
	spin_unlock(&stream->lock);

	return 0;
}

int string_stream_add(struct string_stream *stream, const char *fmt, ...)
{
	va_list args;
	int result;

	va_start(args, fmt);
	result = string_stream_vadd(stream, fmt, args);
	va_end(args);

	return result;
}

void string_stream_clear(struct string_stream *stream)
{
	struct string_stream_fragment *frag_container, *frag_container_safe;

	spin_lock(&stream->lock);
	list_for_each_entry_safe(frag_container,
				 frag_container_safe,
				 &stream->fragments,
				 node) {
		string_stream_fragment_destroy(frag_container);
	}
	stream->length = 0;
	spin_unlock(&stream->lock);
}

char *string_stream_get_string(struct string_stream *stream)
{
	struct string_stream_fragment *frag_container;
	size_t buf_len = stream->length + 1; /* +1 for null byte. */
	struct seq_buf sb;
	char *buf;

	buf = kzalloc(buf_len, stream->gfp);
	if (!buf)
		return NULL;

	seq_buf_init(&sb, buf, buf_len);

	spin_lock(&stream->lock);
	list_for_each_entry(frag_container, &stream->fragments, node)
		seq_buf_puts(&sb, frag_container->fragment);
	spin_unlock(&stream->lock);

	return buf;
}

int string_stream_append(struct string_stream *stream,
			 struct string_stream *other)
{
	const char *other_content;
	int ret;

	other_content = string_stream_get_string(other);

	if (!other_content)
		return -ENOMEM;

	ret = string_stream_add(stream, other_content);
	kfree(other_content);

	return ret;
}

bool string_stream_is_empty(struct string_stream *stream)
{
	return list_empty(&stream->fragments);
}

struct string_stream *alloc_string_stream(gfp_t gfp)
{
	struct string_stream *stream;

	stream = kzalloc_obj(*stream, gfp);
	if (!stream)
		return ERR_PTR(-ENOMEM);

	stream->gfp = gfp;
	INIT_LIST_HEAD(&stream->fragments);
	spin_lock_init(&stream->lock);

	return stream;
}

void string_stream_destroy(struct string_stream *stream)
{
	KUNIT_STATIC_STUB_REDIRECT(string_stream_destroy, stream);

	if (IS_ERR_OR_NULL(stream))
		return;

	string_stream_clear(stream);
	kfree(stream);
}

static void resource_free_string_stream(void *p)
{
	struct string_stream *stream = p;

	string_stream_destroy(stream);
}

struct string_stream *kunit_alloc_string_stream(struct kunit *test, gfp_t gfp)
{
	struct string_stream *stream;

	stream = alloc_string_stream(gfp);
	if (IS_ERR(stream))
		return stream;

	if (kunit_add_action_or_reset(test, resource_free_string_stream, stream) != 0)
		return ERR_PTR(-ENOMEM);

	return stream;
}

void kunit_free_string_stream(struct kunit *test, struct string_stream *stream)
{
	kunit_release_action(test, resource_free_string_stream, (void *)stream);
}
