/**
 * @file staticstring.c
 * @brief Implements the staticstring subsystem.
 */

#include <akerror.h>
#include <akstdlib.h>
#include <akgl/staticstring.h>

akerr_ErrorContext *akgl_string_initialize(akgl_String *obj, char *init)
{
    PREPARE_ERROR(errctx);
    FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "Attempted to initialize NULL string reference");
    if ( init != NULL ) {
	PASS(errctx, aksl_strncpy((char *)&obj->data, sizeof(obj->data), init, sizeof(obj->data) - 1));
    } else {
	// sizeof(obj->data), not sizeof(akgl_String). `data` starts after the
	// `refcount` in front of it, so zeroing the size of the whole struct
	// from the start of the buffer ran four bytes past the end of the
	// object -- into the next pool slot's refcount, which is what makes a
	// free slot look claimed or a claimed one look free.
	memset(&obj->data, 0x00, sizeof(obj->data));
    }
    obj->refcount = 1;
    SUCCEED_RETURN(errctx);
}

akerr_ErrorContext *akgl_string_copy(akgl_String *src, akgl_String *dest, int count)
{
    PREPARE_ERROR(errctx);
    FAIL_ZERO_RETURN(errctx, src, AKERR_NULLPOINTER, "NULL argument");
    FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL argument");
    if ( count == 0 ) {
	count = AKGL_MAX_STRING_LENGTH;
    }
    // Both buffers are exactly AKGL_MAX_STRING_LENGTH bytes, so a larger count
    // walks off the end of two pool slots at once. Refused rather than
    // documented, which is what it used to be.
    FAIL_NONZERO_RETURN(
	errctx,
	((count < 0) || (count > AKGL_MAX_STRING_LENGTH)),
	AKERR_OUTOFBOUNDS,
	"Copy count %d is outside 0..%d",
	count,
	AKGL_MAX_STRING_LENGTH);
    PASS(errctx, aksl_strncpy((char *)&dest->data, sizeof(dest->data), (char *)&src->data, count));
    SUCCEED_RETURN(errctx);
}
