diff dowa/d_string.c @ 260:1f9877b637e9

Add Copilot-powered cyberpunk JRPG chat Integrate the production JRPG chat with Seobeo streaming, Deita persistence, and a Bazel-managed Copilot SDK and LiteLLM inference stack. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <mrjunejune@users.noreply.github.com>
date Wed, 05 Aug 2026 09:19:41 -0700
parents a2720eac50ce
children 04fee26ecce0
line wrap: on
line diff
--- a/dowa/d_string.c	Wed Aug 05 09:19:41 2026 -0700
+++ b/dowa/d_string.c	Wed Aug 05 09:19:41 2026 -0700
@@ -178,8 +178,17 @@
   (*pos)++;
   int32 start = *pos;
 
-  while (*pos < len && json[*pos] != '"')
+  while (*pos < len)
+  {
+    if (json[*pos] == '\\' && *pos + 1 < len)
+    {
+      *pos += 2;
+      continue;
+    }
+    if (json[*pos] == '"')
+      break;
     (*pos)++;
+  }
 
   int32 slen = *pos - start;
   char *str = arena ? Dowa_Arena_Allocate(arena, slen + 1) : malloc(slen + 1);
@@ -410,3 +419,54 @@
     return FALSE;
   return val->bool_val;
 }
+
+char *Dowa_JSON_Escape_String(
+    const char *value,
+    size_t length,
+    Dowa_Arena *p_arena)
+{
+  if (!value || !p_arena)
+    return NULL;
+  if (length == 0)
+    length = strlen(value);
+
+  if (length > (((size_t)-1) - 1) / 6)
+    return NULL;
+  char *escaped = Dowa_Arena_Allocate(p_arena, length * 6 + 1);
+  if (!escaped)
+    return NULL;
+
+  static const char hex[] = "0123456789abcdef";
+  size_t output = 0;
+  for (size_t i = 0; i < length; i++)
+  {
+    uint8 c = (uint8)value[i];
+    switch (c)
+    {
+      case '"': escaped[output++] = '\\'; escaped[output++] = '"'; break;
+      case '\\': escaped[output++] = '\\'; escaped[output++] = '\\'; break;
+      case '\b': escaped[output++] = '\\'; escaped[output++] = 'b'; break;
+      case '\f': escaped[output++] = '\\'; escaped[output++] = 'f'; break;
+      case '\n': escaped[output++] = '\\'; escaped[output++] = 'n'; break;
+      case '\r': escaped[output++] = '\\'; escaped[output++] = 'r'; break;
+      case '\t': escaped[output++] = '\\'; escaped[output++] = 't'; break;
+      default:
+        if (c < 0x20)
+        {
+          escaped[output++] = '\\';
+          escaped[output++] = 'u';
+          escaped[output++] = '0';
+          escaped[output++] = '0';
+          escaped[output++] = hex[c >> 4];
+          escaped[output++] = hex[c & 0x0f];
+        }
+        else
+        {
+          escaped[output++] = (char)c;
+        }
+        break;
+    }
+  }
+  escaped[output] = '\0';
+  return escaped;
+}