#include <k/type.h>
#include <k/io.h>
#include <k/str.h>
kcond
ksbufput(ksbuf* b, ksraw src) {
ksmut dest = { b->run - (b->cur - b->buf), b->cur };
/* there are a number of scenarios we need to account for:
*
* - the ksraw has an unknown size. in this case, we
* determine the size with kssz and proceed according to
* the following rules. we could also count the string
* as we copy, taking advantage of kscp's behavior on
* strings of unknown length, but this would drastically
* complicate the code for an almost certainly negligible
* gain in performance.
*
* - the ksraw has a known size that is shorter than the
* remaining space in the buffer. in this case, we copy
* it into the buffer and return the result of the copy.
*
* - the ksraw has a known size that is the same as the
* remaining space in the buffer. in this case, we copy
* it into the buffer and flush the buffer immediately.
*
* - the ksraw has a known size that is longer than the
* remaining space in the buffer. in this case, we flush
* the buffer immediately and then copy in the new string.
*
* - the ksraw has a known size that is greater than or
* equal to the buffer's run. in this case, we flush the
* buffer and print the ksraw directly, bypassing the
* buffer as it would only be a performance impediment.
*/
if (src.size == 0) src.size = kssz(src.ptr, -1);
if (src.size < dest.size) {
kcond c = kscp(src, dest, null);
if (!kokay(c)) return c;
b -> cur += src.size;
return kscond_ok;
} else if (src.size == dest.size) {
kcond c = kscp(src, dest, null);
if (!kokay(c)) return c;
b -> cur += src.size;
return ksbufflush(b);
} else if (src.size > b -> run) {
kcond c = ksbufflush(b);
if (!kokay(c)) return c;
return kiosend(b -> channel, src, null);
} else if (src.size > dest.size) {
kcond c = ksbufflush(b);
if (!kokay(c)) return c;
dest.size = b -> run;
dest.ptr = b -> cur;
c = kscp(src, dest, null);
if (!kokay(c)) return c;
b -> cur += src.size;
return kscond_ok;
} else return kscond_fail; /* what in the sam heck */
}