11#if PC_ENABLE_SPA_ROUTER
15bool pc_spa_has_extension(
const char *path)
22 const char *slash = strrchr(path,
'/');
23 const char *seg = slash ? slash + 1 : path;
24 const char *dot = strrchr(seg,
'.');
25 return dot && dot != seg && dot[1] !=
'\0';
28pc_spa_action pc_spa_route(
const char *path,
const char *api_prefix)
30 if (!path || path[0] ==
'\0' || (path[0] ==
'/' && path[1] ==
'\0'))
32 return pc_spa_action::PC_SPA_SERVE_SHELL;
35 if (api_prefix && api_prefix[0])
38 if (strncmp(path, api_prefix, pl) == 0)
40 return pc_spa_action::PC_SPA_PASSTHROUGH;
44 return pc_spa_has_extension(path) ? pc_spa_action::PC_SPA_SERVE_FILE : pc_spa_action::PC_SPA_SERVE_SHELL;
47pc_spa_action pc_spa_route_ex(
const char *path,
const pc_spa_ctx *ctx)
51 return pc_spa_route(path,
nullptr);
54 pc_spa_action a = pc_spa_route(path, ctx->api_prefix);
58 if (a != pc_spa_action::PC_SPA_SERVE_SHELL)
62 if (!ctx->shell_available || !ctx->client_scripting || ctx->degraded)
64 return pc_spa_action::PC_SPA_SERVE_FALLBACK;
73void pc_ui_stream_begin(pc_ui_stream *s,
const pc_ui_fragment *frags,
size_t count,
void *ctx)
80 s->count = frags ? count : 0;
84 s->done = (s->count == 0);
87size_t pc_ui_stream_next(pc_ui_stream *s,
char *out,
size_t cap)
89 if (!s || !out || cap == 0 || s->done)
95 while (written < cap && s->idx < s->count)
97 const pc_ui_fragment *f = &s->frags[s->idx];
100 if (!f->html || (f->when && !f->when(s->ctx)))
106 const char *src = f->html + s->off;
107 size_t room = cap - written;
109 while (n < room && src[n] !=
'\0')
113 memcpy(out + written, src, n);
122 if (s->idx >= s->count)
129bool pc_ui_stream_done(
const pc_ui_stream *s)
131 return !s || s->done;
#define MAX_PATH_LEN
Maximum URL path length (including leading /).
Single-page-app micro-routing + conditional UI streaming (PC_ENABLE_SPA_ROUTER).