#ifndef VSTRINGS_H_INCLUDED
#define VSTRINGS_H_INCLUDED


#if __STDC_VERSION__ < 201112L
#	error "Code requires C11 or later to compile"
#endif


#include <stdbool.h>
#include <string.h>

typedef struct { size_t max; size_t len; char *str; } VS_string;

#define VS_set(D, S) _Generic((S), VS_string *: VS_vset, char *: VS_cset) ((D), (S))
#define VS_app(D, S) _Generic((S), VS_string *: VS_vapp, char *: VS_capp) ((D), (S))
#define VS_pre(D, S) _Generic((S), VS_string *: VS_vpre, char *: VS_cpre) ((D), (S))
#define VS_setn(D, N, S) _Generic((S), VS_string *: VS_vsetn, char *: VS_csetn) ((D), (N), (S))
#define VS_appn(D, N, S) _Generic((S), VS_string *: VS_vappn, char *: VS_cappn) ((D), (N), (S))
#define VS_pren(D, N, S) _Generic((S), VS_string *: VS_vpren, char *: VS_cpren) ((D), (N), (S))

VS_string *VS_new(VS_string self[restrict static 1], size_t max);
VS_string *VS_from(VS_string self[restrict static 1], size_t max, char cstr[restrict static max]);
VS_string *VS_free(VS_string self[restrict static 1]);


VS_string *VS_vset(VS_string dest[restrict static 1], VS_string src[restrict static 1]);
VS_string *VS_vapp(VS_string dest[restrict static 1], VS_string src[restrict static 1]);
VS_string *VS_vpre(VS_string dest[restrict static 1], VS_string src[restrict static 1]);
VS_string *VS_vsetn(VS_string dest[restrict static 1], size_t n, VS_string src[restrict static 1]);
VS_string *VS_vappn(VS_string dest[restrict static 1], size_t n, VS_string src[restrict static 1]);
VS_string *VS_vpren(VS_string dest[restrict static 1], size_t n, VS_string src[restrict static 1]);

VS_string *VS_cset(VS_string dest[restrict static 1], char src[restrict static 1]);
VS_string *VS_capp(VS_string dest[restrict static 1], char src[restrict static 1]);
VS_string *VS_cpre(VS_string dest[restrict static 1], char src[restrict static 1]);
VS_string *VS_csetn(VS_string dest[restrict static 1], size_t n, char src[restrict static 1]);
VS_string *VS_cappn(VS_string dest[restrict static 1], size_t n, char src[restrict static 1]);
VS_string *VS_cpren(VS_string dest[restrict static 1], size_t n, char src[restrict static 1]);


typedef struct { void(*fn)(void *); void *args; } VS_ehandle;
extern _Thread_local VS_ehandle VS_emem;

#endif
