summaryrefslogtreecommitdiff
path: root/third_party/mcpc/src/ucbr.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/mcpc/src/ucbr.c')
-rw-r--r--third_party/mcpc/src/ucbr.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/third_party/mcpc/src/ucbr.c b/third_party/mcpc/src/ucbr.c
new file mode 100644
index 0000000..5dfce26
--- /dev/null
+++ b/third_party/mcpc/src/ucbr.c
@@ -0,0 +1,288 @@
+// This file is part of the mcpc library.
+//
+// Copyright (C) 2025 Michael Lee <micl2e2 AT proton.me>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so,
+// subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include "ucbr.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "alloc.h"
+#include "anydata.h"
+#include "errcode.h"
+#include "ext_string.h"
+
+/* = = = = = = = = = = = = = = = = ucbrchd = = = = = = = = = = = = = = = = */
+
+mcpc_ucbrchd_t *
+mcpc_ucbrchd_new_vprintf8 (const char8_t *fmt, va_list *vargs)
+{
+ size_t sbuf_cap = 1024;
+ size_t sbuf_len = 0;
+ char8_t *sbuf = mcpc_alloc (sbuf_cap);
+ int printed = 0;
+ while (true)
+ {
+ va_list vargs_cp;
+ va_copy (vargs_cp, *vargs);
+ printed
+ = vsnprintf ((char *)sbuf, sbuf_cap, (const char *)fmt, vargs_cp);
+ bug_if (printed < 0);
+ if ((size_t)printed >= sbuf_cap)
+ {
+ sbuf_cap += sbuf_cap;
+ sbuf = mcpc_realloc (sbuf, sbuf_cap);
+ }
+ else
+ {
+ sbuf_len = (size_t)printed;
+ break;
+ }
+ }
+
+ mcpc_anydata_t *anydata = mcpc_anydata_new_typ (MCPC_U8STR);
+
+ if (MCPC_EC_0 != mcpc_anydata_set_u8str (anydata, sbuf, sbuf_len))
+ goto badret;
+
+ free (sbuf);
+ return (mcpc_ucbrchd_t *)anydata;
+
+badret:
+ free (sbuf);
+ mcpc_anydata_free (anydata);
+ return nullptr;
+}
+
+mcpc_errcode_t
+mcpc_ucbrchd_getref_u8str (const mcpc_ucbrchd_t *ucbrchd, const char8_t **ret,
+ size_t *ret_len)
+{
+ return mcpc_anydata_getref_u8str (ucbrchd, ret, ret_len);
+}
+
+mcpc_errcode_t
+mcpc_ucbrchd_get_data_type (const mcpc_ucbrchd_t *ucbrchd, mcpc_anytype_t *ret)
+{
+ bug_if_nullptr (ucbrchd);
+ bug_if_nullptr (ret);
+
+ *ret = ucbrchd->data_typ;
+
+ return MCPC_EC_0;
+}
+
+bool
+mcpc_ucbrchd_is_tool_callres (const mcpc_ucbrchd_t *ucbrchd)
+{
+ return ucbrchd->flags & ANYDATA_FL_USRCBRES_TOOLCALL;
+}
+
+bool
+mcpc_ucbrchd_is_prmpt_callres (const mcpc_ucbrchd_t *ucbrchd)
+{
+ return ucbrchd->flags & ANYDATA_FL_USRCBRES_PRMPTCALL;
+}
+
+bool
+mcpc_ucbrchd_is_assist_prmpt (const mcpc_ucbrchd_t *ucbrchd)
+{
+ return ucbrchd->flags & ANYDATA_FL_USRCBRES_PRMPTCALL_ASSIST;
+}
+
+/* = = = = = = = = = = = = = = = = = ucbr = = = = = = = = = = = = = = = = = */
+
+mcpc_ucbr_t *
+mcpc_ucbr_new ()
+{
+ return mcpc_anypool_new ();
+}
+
+void
+mcpc_ucbr_free (mcpc_ucbr_t *ucbr)
+{
+ mcpc_anypool_free (ucbr);
+}
+
+void
+mcpc_ucbr_addcpy (mcpc_ucbr_t *ucbr, const mcpc_ucbrchd_t *ucbrchd)
+{
+ mcpc_anypool_addcpy (ucbr, ucbrchd);
+}
+
+void
+mcpc_ucbr_addfre (mcpc_ucbr_t *ucbr, mcpc_ucbrchd_t *ucbrchd)
+{
+ mcpc_anypool_addfre (ucbr, ucbrchd);
+}
+
+bool
+mcpc_ucbr_is_err (const mcpc_ucbr_t *ucbr)
+{
+ bug_if_nullptr (ucbr);
+ return ucbr->flags & ANYPOOL_FL_USRCBRES_TOOLCALL_ERROR;
+}
+
+size_t
+mcpc_ucbr_get_len (const mcpc_ucbr_t *ucbr)
+{
+ bug_if_nullptr (ucbr);
+ size_t ret = 0;
+ ret = ((const mcpc_anypool_t *)ucbr)->len;
+ return ret;
+}
+
+const mcpc_ucbrchd_t *
+mcpc_ucbr_get (const mcpc_ucbr_t *ucbr, size_t idx)
+{
+ return mcpc_anypool_get (ucbr, idx);
+}
+
+const mcpc_ucbrchd_t *
+mcpc_ucbr_getbyname (const mcpc_ucbr_t *ucbr, const char8_t *name,
+ size_t name_len)
+{
+ return mcpc_anypool_getbymeta1 (ucbr, name, name_len);
+}
+
+const mcpc_ucbrchd_t *
+mcpc_ucbr_get_next (const mcpc_ucbr_t *ucbr)
+{
+ bug_if_nullptr (ucbr);
+
+ static size_t idx = 0;
+
+ const mcpc_anypool_t *pool = ucbr;
+ if (pool == nullptr)
+ return nullptr;
+
+ const size_t pool_len = pool->len;
+ if (pool_len == 0)
+ return nullptr;
+
+ if (idx == pool_len) // TODO MT-SAFE
+ {
+ idx = 0;
+ return nullptr;
+ }
+
+ const mcpc_anydata_t *ret = pool->head + idx;
+ idx += 1;
+
+ return ret;
+}
+
+size_t
+mcpc_ucbr_get_serlz_lenhint (const mcpc_ucbr_t *ucbr)
+{
+ bug_if_nullptr (ucbr);
+ size_t ret = 0;
+
+ size_t length = mcpc_ucbr_get_len (ucbr);
+ for (size_t i = 0; i < length; ++i)
+ {
+ const mcpc_ucbrchd_t *cur_chd = mcpc_ucbr_get (ucbr, i);
+ ret += cur_chd->data_len;
+ }
+
+ /* JSON string escaping can expand one input byte to six output bytes. */
+ if (ret > (SIZE_MAX - 1024) / 6)
+ return 0;
+ ret = ret * 6 + 1024;
+
+ return ret;
+}
+
+void
+mcpc_ucbr_toolcallres_add_text_vprintf8 (mcpc_ucbr_t *ucbr, const char8_t *fmt,
+ va_list *vargs)
+{
+ bug_if_nullptr (ucbr);
+ bug_if_nullptr (fmt);
+ bug_if_nullptr (vargs);
+
+ ucbr->flags |= ANYPOOL_FL_USRCBRES_TOOLCALL;
+
+ mcpc_ucbrchd_t *newctn = mcpc_ucbrchd_new_vprintf8 (fmt, vargs);
+ newctn->flags |= ANYDATA_FL_USRCBRES_TOOLCALL;
+ newctn->flags |= ANYDATA_FL_USRCBRES_TOOLCALL_TXTCTN;
+ mcpc_ucbr_addfre (ucbr, newctn);
+}
+
+MCPC_API void
+mcpc_ucbr_toolcall_add_text_printf8 (mcpc_ucbr_t *ucbr, const char8_t *fmt,
+ ...)
+{
+ va_list vargs;
+ va_start (vargs, fmt);
+
+ mcpc_ucbr_toolcallres_add_text_vprintf8 (ucbr, fmt, &vargs);
+
+ va_end (vargs);
+}
+
+MCPC_API void
+mcpc_ucbr_toolcall_add_errmsg_printf8 (mcpc_ucbr_t *ucbr, const char8_t *fmt,
+ ...)
+{
+ va_list vargs;
+ va_start (vargs, fmt);
+
+ ucbr->flags |= ANYPOOL_FL_USRCBRES_TOOLCALL_ERROR;
+ mcpc_ucbr_toolcallres_add_text_vprintf8 (ucbr, fmt, &vargs);
+
+ va_end (vargs);
+}
+
+MCPC_API void
+mcpc_ucbr_prmptget_add_user_printf8 (mcpc_ucbr_t *ucbr, const char8_t *fmt,
+ ...)
+{
+ va_list vargs;
+ va_start (vargs, fmt);
+
+ ucbr->flags |= ANYPOOL_FL_USRCBRES_PRMPTCALL;
+
+ mcpc_ucbrchd_t *newctn = mcpc_ucbrchd_new_vprintf8 (fmt, &vargs);
+ newctn->flags |= ANYDATA_FL_USRCBRES_PRMPTCALL;
+
+ mcpc_ucbr_addfre (ucbr, newctn);
+
+ va_end (vargs);
+}
+
+MCPC_API void
+mcpc_ucbr_prmptget_add_assist_printf8 (mcpc_ucbr_t *ucbr, const char8_t *fmt,
+ ...)
+{
+ va_list vargs;
+ va_start (vargs, fmt);
+
+ ucbr->flags |= ANYPOOL_FL_USRCBRES_PRMPTCALL;
+
+ mcpc_ucbrchd_t *newctn = mcpc_ucbrchd_new_vprintf8 (fmt, &vargs);
+ newctn->flags |= ANYDATA_FL_USRCBRES_PRMPTCALL;
+ newctn->flags |= ANYDATA_FL_USRCBRES_PRMPTCALL_ASSIST;
+
+ mcpc_ucbr_addfre (ucbr, newctn);
+
+ va_end (vargs);
+}