From 7d4e99a319b6b344804de31b354632707c56b8fd Mon Sep 17 00:00:00 2001 From: "peng.li24" <734991033@qq.com> Date: Mon, 7 Sep 2026 21:30:17 +0800 Subject: [PATCH] =?UTF-8?q?head=20=E4=B8=89=E8=BD=B4=E9=87=8D=E6=9E=84?= =?UTF-8?q?=EF=BC=9Alayout/runtime/runtime-rs=20=E9=80=82=E9=85=8D=20ref/s?= =?UTF-8?q?toretype/langtype?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参数槽 isptr → ref;code/ffi/kvkind 与运行时 codec 同步三轴 head 语义。 --- layout/src/code.rs | 2 +- layout/src/ffi.rs | 47 ++-- layout/src/kvkind.rs | 12 +- runtime-rs/src/engine.rs | 79 +++++- runtime-rs/src/ffi.rs | 36 ++- runtime/src/kv.c | 64 +++-- runtime/src/runtime_internal.h | 41 +-- runtime/src/xvalue.c | 460 ++++++++++++++++++++++++--------- 8 files changed, 530 insertions(+), 211 deletions(-) diff --git a/layout/src/code.rs b/layout/src/code.rs index 8ee8d79b..08585afe 100644 --- a/layout/src/code.rs +++ b/layout/src/code.rs @@ -2,7 +2,7 @@ //! //! 存储约定: //! /lib/·/[0,0] 布局后签名(kind=rwfunc) -//! /lib/·/ 命名参数→slot 指针(kind=char, isptr=1) +//! /lib/·/ 命名参数→slot 指针(langtype=char, ref=1) //! /lib/·/[i,j] 编译后指令(kind=rwir),i 从 1 开始 //! /lib/·/‥labels/ label → irseq //! /lib/·.src 源码副本 diff --git a/layout/src/ffi.rs b/layout/src/ffi.rs index 79b24df3..2f075abe 100644 --- a/layout/src/ffi.rs +++ b/layout/src/ffi.rs @@ -38,12 +38,15 @@ extern "C" { err: *mut c_char, err_cap: u32, ) -> c_int; - /// 新位置写:按 (xkind, kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。 + /// 新位置写:按 (ref, storetype, ro, vid, langtype, body_len) 分配新 box、写 head,返回 body 偏移指针。 fn kvspaceWriteNewPlace( h: Handle, key: *const c_char, - xkind: u8, - kindexpr: *const c_char, + r#ref: u8, + storetype: u8, + ro: u8, + vid: u32, + langtype: *const c_char, body_len: u32, body: *mut *mut u8, err: *mut c_char, @@ -116,17 +119,20 @@ extern "C" { fn kvspaceNewFloat64(v: f64, out: *mut *mut u8, out_len: *mut u32) -> c_int; } -/// XValueHead 解码结果(与 kvspace-durable 的 kvspaceHead_t 布局一致)。kindexpr 为唯一类型真相。 +/// XValueHead 解码结果(与 kvspace/include/kvspace/kvspace.h 的 kvspaceHead_t 逐字段对齐)。 +/// 三正交轴 ref×storetype×langtype;langtype 为语义类型真相(含 [dims]、无 ptr/ext 前缀)。 #[repr(C)] pub struct kvspaceHead_t { - pub xkind: u8, - pub kindexpr: [u8; 256], - pub kind_off: i32, - pub ndim: i32, - pub dims: [i32; 8], + pub headlen: u16, + pub r#ref: u8, + pub storetype: u8, pub ro: u8, pub vid: u32, pub body_len: i32, + pub ndim: i32, + pub dims: [i32; 8], + pub langtype: [u8; 256], + pub langtype_len: i32, pub body_offset: i32, } @@ -195,8 +201,8 @@ impl Kv { fn write_new_place(&mut self, key: &str, tlv: &[u8]) -> Result<(), String> { let h = decode_head(tlv); - let klen = h.kindexpr.iter().position(|&b| b == 0).unwrap_or(0); - let kindexpr = CString::new(&h.kindexpr[..klen]).expect("no NUL in kindexpr"); + let llen = h.langtype.iter().position(|&b| b == 0).unwrap_or(0); + let langtype = CString::new(&h.langtype[..llen]).expect("no NUL in langtype"); let ck = CString::new(key).expect("no NUL in key"); let body_off = h.body_offset as usize; let body_len = h.body_len.max(0) as usize; @@ -206,8 +212,11 @@ impl Kv { kvspaceWriteNewPlace( self.h, ck.as_ptr(), - h.xkind, - kindexpr.as_ptr(), + h.r#ref, + h.storetype, + h.ro, + h.vid, + langtype.as_ptr(), body_len as u32, &mut body, err.as_mut_ptr(), @@ -350,14 +359,16 @@ pub fn tlv_encode(kind: &str, raw: &[u8], array_len: i32) -> Vec { /// 解码 XValueHead。 pub fn decode_head(data: &[u8]) -> kvspaceHead_t { let mut h = kvspaceHead_t { - xkind: 0, - kindexpr: [0u8; 256], - kind_off: 0, - ndim: 0, - dims: [0i32; 8], + headlen: 0, + r#ref: 0, + storetype: 0, ro: 0, vid: 0, body_len: 0, + ndim: 0, + dims: [0i32; 8], + langtype: [0u8; 256], + langtype_len: 0, body_offset: 0, }; unsafe { diff --git a/layout/src/kvkind.rs b/layout/src/kvkind.rs index bac60325..79baa833 100644 --- a/layout/src/kvkind.rs +++ b/layout/src/kvkind.rs @@ -38,7 +38,7 @@ pub fn head(data: &[u8]) -> ffi::kvspaceHead_t { ffi::decode_head(data) } -/// 解析 kindexpr 内容 → (dims, base kind)。kindexpr 无前缀(ref/ptr 归 head.xkind)。 +/// 解析 kindexpr 内容 → (dims, base kind)。kindexpr 无前缀(ref/ptr 归 head.ref)。 pub fn parse_kindexpr(kx: &str) -> (Vec, String) { if kx.starts_with('[') { match kx.find(']') { @@ -64,11 +64,11 @@ pub fn kindexpr(data: &[u8]) -> String { } let h = ffi::decode_head(data); let end = h - .kindexpr + .langtype .iter() .position(|&b| b == 0) - .unwrap_or(h.kindexpr.len()); - String::from_utf8_lossy(&h.kindexpr[..end]).into_owned() + .unwrap_or(h.langtype.len()); + String::from_utf8_lossy(&h.langtype[..end]).into_owned() } pub fn kind(data: &[u8]) -> String { @@ -79,7 +79,7 @@ pub fn kind(data: &[u8]) -> String { } pub fn is_ptr(data: &[u8]) -> bool { - !data.is_empty() && ffi::decode_head(data).xkind == 1 + !data.is_empty() && ffi::decode_head(data).r#ref == 1 } pub fn array_len(data: &[u8]) -> i32 { @@ -128,7 +128,7 @@ pub fn display(data: &[u8]) -> String { } let h = ffi::decode_head(data); let b = body(data, &h); - if h.xkind == 1 { + if h.r#ref == 1 { return format!("→{}:{}", String::from_utf8_lossy(b), k); } format!("{}:{}", k, plain_value(&k, b)) diff --git a/runtime-rs/src/engine.rs b/runtime-rs/src/engine.rs index 16b92f8b..e417af19 100644 --- a/runtime-rs/src/engine.rs +++ b/runtime-rs/src/engine.rs @@ -7,6 +7,40 @@ use std::ptr::null_mut; use crate::ffi::*; use crate::rwir; +const KVSPACE_REF_EXT: u8 = 2; +const STORETYPE_ATOM: u8 = 1; +const STORETYPE_ARRAYND: u8 = 2; +const STORETYPE_INDEX: u8 = 3; +const STORETYPE_EXTINDEX: u8 = 4; + +/// 由完整 langtype kindexpr 串推 storetype(镜像 kvspace-durable::storetype_from_kindexpr): +/// extindex / index(含 rwfunc/defrwir) / 对象(·)·路径(/) → INDEX 系;带 [dims] → ARRAYND;否则 ATOM。 +fn storetype_from_kindexpr(kx: &str) -> u8 { + if kx.is_empty() { + return 0; + } + let (has_dims, base) = match kx.strip_prefix('[') { + Some(_) => match kx.find(']') { + Some(e) => (true, &kx[e + 1..]), + None => (false, kx), + }, + None => (false, kx), + }; + if base == "extindex" { + return STORETYPE_EXTINDEX; + } + if matches!(base, "index" | "rwfunc" | "defrwir") + || base.starts_with('/') + || base.contains('\u{b7}') + { + return STORETYPE_INDEX; + } + if has_dims { + return STORETYPE_ARRAYND; + } + STORETYPE_ATOM +} + pub struct Engine { pub rt: *mut c_void, // kvlang runtime 句柄 pub kv: *mut c_void, // kvspace 句柄(自持,同时传给 rwirext) @@ -17,10 +51,19 @@ pub struct Engine { impl Engine { // ── kvspace 读写(绝对路径,char/utf8 与 char/utf32 编解码)───────── - /// 写即构造:按 (kindexpr, body) 向 kvspace 要偏移指针后直接写 body 字节—— + /// 写即构造:按三正交轴 (ref, storetype, ro, vid, langtype) + body 向 kvspace 要偏移指针后直接写 body 字节—— /// key 已存在且同 body_len → WriteInPlace(原 box 就地);否则 WriteNewPlace(新 box)。 /// 两分支各调唯一原语、无预 encode 整条 TLV、无中转 buffer、无 free。 - fn write_construct(&self, key: &str, xkind: u8, kindexpr: &str, body: &[u8]) { + fn write_construct( + &self, + key: &str, + r#ref: u8, + storetype: u8, + ro: u8, + vid: u32, + langtype: &str, + body: &[u8], + ) { unsafe { let ck = cs(key); let mut bp: *mut u8 = null_mut(); @@ -38,8 +81,11 @@ impl Engine { kvspaceWriteNewPlace( self.kv, ck.as_ptr(), - xkind, - cs(kindexpr).as_ptr(), + r#ref, + storetype, + ro, + vid, + cs(langtype).as_ptr(), body.len() as u32, &mut bp, err.as_mut_ptr() as *mut c_char, @@ -91,7 +137,16 @@ impl Engine { /// 扩展世界(@ ref=2)句柄编码写入:kind=目标完整 kindexpr(如 "[]uint8"),body=定位串。 /// 读取该 key 时由 read_at 按 body 前缀路由给对应 /lib/networld/* 兑现器还原真实字节。 pub fn set_ext_handle(&self, key: &str, target_kindexpr: &str, locator: &str) { - self.write_construct(key, 2, target_kindexpr, locator.as_bytes()); + let st = storetype_from_kindexpr(target_kindexpr); + self.write_construct( + key, + KVSPACE_REF_EXT, + st, + 0, + 0, + target_kindexpr, + locator.as_bytes(), + ); } /// 读 key 的 head,返回 (ref, body 串)。仅 ref==2 时 body 有意义(扩展句柄定位串)。 @@ -103,7 +158,7 @@ impl Engine { unsafe { let mut head = KvspaceHead::default(); kvspaceDecodeHead(tlv.as_ptr(), tlv.len() as u32, &mut head); - let r = match head.xkind { + let r = match head.r#ref { 2 => 2, 1 => 1, _ => 0, @@ -173,7 +228,7 @@ impl Engine { if kvspaceDecodeHead(tlv.as_ptr(), tlv.len() as u32, &mut h) != 0 { return Vec::new(); } - let r = match h.xkind { + let r = match h.r#ref { 2 => 2, 1 => 1, _ => 0, @@ -292,7 +347,15 @@ impl Engine { .trim_end_matches('\0') .to_string(); let (bo, bl) = (head.body_offset as usize, head.body_len.max(0) as usize); - self.write_construct(key, head.xkind, &kx, &tlv[bo..bo + bl]); + self.write_construct( + key, + head.r#ref, + head.storetype, + head.ro, + head.vid, + &kx, + &tlv[bo..bo + bl], + ); } } diff --git a/runtime-rs/src/ffi.rs b/runtime-rs/src/ffi.rs index 66423bec..8e4de099 100644 --- a/runtime-rs/src/ffi.rs +++ b/runtime-rs/src/ffi.rs @@ -5,31 +5,36 @@ use std::ffi::{c_char, c_int, c_void, CStr, CString}; -/// kvspaceDecodeHead 输出(与 kvspace-durable/src/ffi.rs::kvspaceHead_t 对齐)。kindexpr 为唯一类型真相。 +/// kvspaceDecodeHead 输出(逐字段对齐 kvspace/include/kvspace/kvspace.h 的 kvspaceHead_t)。 +/// 三正交轴 ref×storetype×langtype;kindexpr 即该 ABI 的 langtype 槽(本 runtime 内部沿用 kindexpr 命名)。 #[repr(C)] pub struct KvspaceHead { - pub xkind: u8, - pub kindexpr: [u8; 256], - pub kind_off: i32, - pub ndim: i32, - pub dims: [i32; 8], + pub headlen: u16, + pub r#ref: u8, + pub storetype: u8, pub ro: u8, pub vid: u32, pub body_len: i32, + pub ndim: i32, + pub dims: [i32; 8], + pub kindexpr: [u8; 256], + pub kindexpr_len: i32, pub body_offset: i32, } impl Default for KvspaceHead { fn default() -> Self { KvspaceHead { - xkind: 0, - kindexpr: [0u8; 256], - kind_off: 0, - ndim: 0, - dims: [0i32; 8], + headlen: 0, + r#ref: 0, + storetype: 0, ro: 0, vid: 0, body_len: 0, + ndim: 0, + dims: [0i32; 8], + kindexpr: [0u8; 256], + kindexpr_len: 0, body_offset: 0, } } @@ -99,12 +104,15 @@ unsafe extern "C" { err: *mut c_char, err_cap: u32, ) -> c_int; - /// 新位置写:按 (kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。 + /// 新位置写:按 (ref, storetype, ro, vid, langtype, body_len) 分配新 box、写 head,返回 body 偏移指针。 pub fn kvspaceWriteNewPlace( h: *mut c_void, key: *const c_char, - xkind: u8, - kindexpr: *const c_char, + r#ref: u8, + storetype: u8, + ro: u8, + vid: u32, + langtype: *const c_char, body_len: u32, body: *mut *mut u8, err: *mut c_char, diff --git a/runtime/src/kv.c b/runtime/src/kv.c index 4c2e7ef9..ed28305a 100644 --- a/runtime/src/kv.c +++ b/runtime/src/kv.c @@ -14,21 +14,28 @@ static void kvlangXvalueCopyMalloc(kvlangXvalue_t *out, const uint8_t *d, uint32 kvlangKv_t *kvlangKvConnect(const char *dsn) { kvlangKv_t *k = calloc(1, sizeof(*k)); k->h = kvspaceConnect(dsn); - if (!k->h) { free(k); return NULL; } + if (!k->h) { + free(k); + return NULL; + } return k; } void kvlangKvDisconnect(kvlangKv_t *k) { - if (!k) return; - if (k->h) kvspaceClose(k->h); + if (!k) + return; + if (k->h) + kvspaceClose(k->h); free(k); } /* 借用读(resolve=0,raw)→ 拷贝为 runtime 自持。空值 → out len=0。 */ int kvlangKvGetOne(kvlangKv_t *k, const char *key, kvlangXvalue_t *out) { kvlangXvalueZero(out); - uint8_t *d; uint32_t len; - if (kvspaceGet(k->h, key, 0, &d, &len) != 0) return -1; + uint8_t *d; + uint32_t len; + if (kvspaceGet(k->h, key, 0, &d, &len) != 0) + return -1; kvlangXvalueCopyMalloc(out, d, len); return 0; } @@ -37,11 +44,15 @@ int kvlangKvGetOne(kvlangKv_t *k, const char *key, kvlangXvalue_t *out) { * → 拷贝自持。空值 → out len=0。 */ int kvlangKvGetMember(kvlangKv_t *k, const char *dir, const char *name, kvlangXvalue_t *out) { kvlangXvalueZero(out); - if (!name || !name[0]) return 0; + if (!name || !name[0]) + return 0; size_t dl = strlen(dir), nl = strlen(name); char *key = malloc(dl + nl + 1); - memcpy(key, dir, dl); memcpy(key + dl, name, nl); key[dl + nl] = 0; - uint8_t *d; uint32_t len; + memcpy(key, dir, dl); + memcpy(key + dl, name, nl); + key[dl + nl] = 0; + uint8_t *d; + uint32_t len; if (kvspaceGet(k->h, key, 1, &d, &len) == 0 && d && len > 0) kvlangXvalueCopyMalloc(out, d, len); free(key); @@ -53,27 +64,29 @@ int kvlangKvGetMember(kvlangKv_t *k, const char *dir, const char *name, kvlangXv int kvlangKvSet(kvlangKv_t *k, const kvlangKvPair_t *pairs, int n, char *err, uint32_t err_cap) { for (int i = 0; i < n; i++) { const kvlangXvalue_t *v = &pairs[i].val; - if (!v->data || v->len == 0) { /* None → 删键,令该槽读回 None(不可静默跳过留旧值) */ - const char *dk[1] = { pairs[i].key }; + if (!v->data || v->len == 0) { /* None → 删键,令该槽读回 None(不可静默跳过留旧值) */ + const char *dk[1] = {pairs[i].key}; kvspaceDel(k->h, dk, 1, err, err_cap); continue; } kvspaceHead_t h; - if (kvspaceDecodeHead(v->data, v->len, &h) != 0 || !h.kindexpr[0]) continue; + if (kvspaceDecodeHead(v->data, v->len, &h) != 0 || !h.kindexpr[0]) + continue; uint32_t body_len = h.body_len < 0 ? 0 : (uint32_t)h.body_len; const uint8_t *body = v->data + h.body_offset; uint8_t *dst = NULL; if (kvspaceWriteInPlace(k->h, pairs[i].key, 1, body_len, &dst, err, err_cap) != 0) { - if (kvspaceWriteNewPlace(k->h, pairs[i].key, h.xkind, (const char *)h.kindexpr, body_len, &dst, err, err_cap) != 0) + if (kvspaceWriteNewPlace(k->h, pairs[i].key, h.ref, h.storetype, h.ro, h.vid, (const char *)h.kindexpr, body_len, &dst, err, err_cap) != 0) return -1; } - if (body_len > 0 && dst) memcpy(dst, body, body_len); + if (body_len > 0 && dst) + memcpy(dst, body, body_len); } return 0; } int kvlangKvDel(kvlangKv_t *k, const char *key, char *err, uint32_t err_cap) { - const char *keys[1] = { key }; + const char *keys[1] = {key}; return kvspaceDel(k->h, keys, 1, err, err_cap); } @@ -106,21 +119,26 @@ int kvlangKvDelExtIndex(kvlangKv_t *k, const char *path, char *err, uint32_t err } int kvlangKvList(kvlangKv_t *k, const char *prefix, bool expand_ext, bool resolve, - char ***out_names, int *out_count) { - *out_names = NULL; *out_count = 0; + char ***out_names, int *out_count) { + *out_names = NULL; + *out_count = 0; int ex = expand_ext ? 1 : 0, rs = resolve ? 1 : 0; int32_t count = 0; - if (kvspaceListLen(k->h, prefix, ex, rs, &count) != 0) return -1; - if (count <= 0) return 0; + if (kvspaceListLen(k->h, prefix, ex, rs, &count) != 0) + return -1; + if (count <= 0) + return 0; char **names = malloc(sizeof(char *) * (size_t)count); for (int32_t i = 0; i < count; i++) { - uint8_t buf[1024]; uint32_t len = 0; + uint8_t buf[1024]; + uint32_t len = 0; if (kvspaceListAt(k->h, prefix, ex, rs, i, buf, sizeof buf, &len) == 0) names[i] = strndup((const char *)buf, len); else names[i] = strdup(""); } - *out_names = names; *out_count = (int)count; + *out_names = names; + *out_count = (int)count; return 0; } @@ -128,8 +146,10 @@ int kvlangKvWatch(kvlangKv_t *k, const char *key, const kvlangXvalue_t *target, kvlangXvalueZero(out); const uint8_t *t = target->data ? target->data : (const uint8_t *)""; uint32_t tl = target->len; - uint8_t *d; uint32_t len; - if (kvspaceWatch(k->h, key, t, tl, tick_ns, &d, &len) != 0) return -1; + uint8_t *d; + uint32_t len; + if (kvspaceWatch(k->h, key, t, tl, tick_ns, &d, &len) != 0) + return -1; kvlangXvalueCopyMalloc(out, d, len); return 0; } diff --git a/runtime/src/runtime_internal.h b/runtime/src/runtime_internal.h index a83a7f15..b847b4d2 100644 --- a/runtime/src/runtime_internal.h +++ b/runtime/src/runtime_internal.h @@ -10,23 +10,31 @@ /* ── kvspace-durable C ABI ─────────────────────────────────────────── */ +/* 三正交轴 head(逐字段对齐 kvspace/include/kvspace/kvspace.h 的 kvspaceHead_t)。 + * kindexpr 即该 ABI 的 langtype 槽(本 runtime 内部沿用 kindexpr 命名)。 */ typedef struct { - uint8_t xkind; /* 五分类:0=None 1=Ptr 2=ExtValue 3=DefKindexpr 4=RealValue */ - uint8_t kindexpr[256]; /* NUL 终止(含 [dims]、无前缀,去 padding) */ - int32_t kind_off; /* base 种类在 kindexpr 内的起始字节偏移 */ - int32_t ndim; /* 维数(标量=0) */ - int32_t dims[8]; /* 各维长度(X_MAX_NDIM=8) */ - uint8_t ro; /* 1=只读,0=可写 */ + uint16_t headlen; /* head 总字节数;body 起于偏移 headlen */ + uint8_t ref; /* 存储位置:见 KVSPACE_REF_* */ + uint8_t storetype; /* 物理布局:见 KVSPACE_STORETYPE_* */ + uint8_t ro; /* 1=只读,0=可写 */ uint32_t vid; /* vthread id */ - int32_t body_len; /* body 字节数 */ - int32_t body_offset; /* body 在 data 内的起始偏移(= head_len) */ + int32_t body_len; /* body 字节数 */ + int32_t ndim; /* ARRAYND:维数;index/extindex:3;NONE/ATOM:0 */ + int32_t dims[8]; /* 各维长度 / [len,cap,M](X_MAX_NDIM=8) */ + uint8_t kindexpr[256];/* 语义类型 kindexpr 串,NUL 终止(含 [dims]、无 ref/ext 前缀) */ + int32_t kindexpr_len; /* kindexpr 内容长度(去 padding) */ + int32_t body_offset; /* body 在 data 内的起始偏移(= headlen) */ } kvspaceHead_t; -#define KVSPACE_XKIND_NONE 0 -#define KVSPACE_XKIND_PTR 1 -#define KVSPACE_XKIND_EXTVALUE 2 -#define KVSPACE_XKIND_DEFKINDEXPR 3 -#define KVSPACE_XKIND_REALVALUE 4 +#define KVSPACE_REF_INLINE 0 +#define KVSPACE_REF_PTR 1 +#define KVSPACE_REF_EXT 2 + +#define KVSPACE_STORETYPE_NONE 0 +#define KVSPACE_STORETYPE_ATOM 1 +#define KVSPACE_STORETYPE_ARRAYND 2 +#define KVSPACE_STORETYPE_INDEX 3 +#define KVSPACE_STORETYPE_EXTINDEX 4 extern void *kvspaceConnect(const char *dsn); extern void kvspaceClose(void *h); @@ -35,9 +43,10 @@ extern int kvspaceGet(void *h, const char *key, int resolve, uint8_t **out, ui /* 就地写:key 已存在、body_len==原 body_len → 返回原 box body 偏移指针;否则非 0 + err。 */ extern int kvspaceWriteInPlace(void *h, const char *key, int resolve, uint32_t body_len, uint8_t **body, char *err, uint32_t err_cap); -/* 新位置写:按 (xkind, kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。 */ -extern int kvspaceWriteNewPlace(void *h, const char *key, uint8_t xkind, const char *kindexpr, - uint32_t body_len, uint8_t **body, char *err, uint32_t err_cap); +/* 新位置写:按 (ref, storetype, ro, vid, langtype, body_len) 分配新 box、写 head,返回 body 偏移指针。 */ +extern int kvspaceWriteNewPlace(void *h, const char *key, uint8_t ref, uint8_t storetype, + uint8_t ro, uint32_t vid, const char *langtype, uint32_t body_len, + uint8_t **body, char *err, uint32_t err_cap); /* 前缀遍历:listlen 定计数,逐 idx 取名(借用回收缓冲,不得 free),不一次性返回整段名单。 */ extern int kvspaceListLen(void *h, const char *prefix, int expand_ext, int resolve, int32_t *out_count); extern int kvspaceListAt(void *h, const char *prefix, int expand_ext, int resolve, int32_t idx, diff --git a/runtime/src/xvalue.c b/runtime/src/xvalue.c index 97287f34..3a54d9cf 100644 --- a/runtime/src/xvalue.c +++ b/runtime/src/xvalue.c @@ -9,53 +9,72 @@ static uint64_t rd64(const uint8_t *p) { return (uint64_t)rd32(p) | ((uint64_t)r void kvlangXvalueFree(kvlangXvalue_t *v) { free(v->data); - v->data = NULL; v->len = 0; + v->data = NULL; + v->len = 0; } void kvlangXvalueSetBytes(kvlangXvalue_t *v, uint8_t *data, uint32_t len) { - v->data = data; v->len = len; + v->data = data; + v->len = len; } -/* 解析 kindexpr 内容 → (dims, base kind)。kindexpr 为 NUL 终止串、无前缀(ref 归 head.xkind)。 */ +/* 解析 kindexpr 内容 → (dims, base kind)。kindexpr 为 NUL 终止串、无前缀(ref 归 head.ref)。 */ void kvlang_kindexpr_parse(const uint8_t *kx, kvlang_kindexpr_t *out) { memset(out, 0, sizeof(*out)); - if (!kx) return; + if (!kx) + return; int32_t i = 0; if (kx[i] == '[') { i++; while (kx[i] != ']' && kx[i] != 0 && out->ndim < X_MAX_NDIM) { int32_t d = 0; - while (kx[i] >= '0' && kx[i] <= '9') { d = d * 10 + (kx[i] - '0'); i++; } + while (kx[i] >= '0' && kx[i] <= '9') { + d = d * 10 + (kx[i] - '0'); + i++; + } out->dims[out->ndim++] = d; - if (kx[i] == ',') i++; + if (kx[i] == ',') + i++; } - if (kx[i] == ']') i++; + if (kx[i] == ']') + i++; } out->kind = (const char *)(kx + i); out->kind_len = (int32_t)strlen((const char *)(kx + i)); out->array_len = 1; - for (int d = 0; d < out->ndim; d++) out->array_len *= out->dims[d]; + for (int d = 0; d < out->ndim; d++) + out->array_len *= out->dims[d]; } /* head 编解码统一委托给链接的 kvspace .so(kvspace-c / kvspace-durable 同一 ABI), * runtime 不再私持 TLV head 布局,杜绝多份手写偏移不一致。 */ static int kvlangXvalueDecodeHeadRaw(const uint8_t *d, uint32_t len, kvspaceHead_t *h) { memset(h, 0, sizeof(*h)); - if (!d || len == 0) return -1; + if (!d || len == 0) + return -1; kvspaceDecodeHead(d, len, h); return h->kindexpr[0] ? 0 : -1; } /* array_len → dims:char/* 恒一维(含空串/单字符);其余标量(≤1)=0 维、多元素=1 维。 */ static int32_t al_to_dims(const char *kind, int32_t array_len, int32_t *dims) { - if (strncmp(kind, "char/", 5) == 0) { dims[0] = array_len < 0 ? 0 : array_len; return 1; } - if (array_len > 1) { dims[0] = array_len; return 1; } + if (strncmp(kind, "char/", 5) == 0) { + dims[0] = array_len < 0 ? 0 : array_len; + return 1; + } + if (array_len > 1) { + dims[0] = array_len; + return 1; + } return 0; } /* .so 分配的 TLV → 转交 runtime 所有权(统一 free 释放)。 */ static uint8_t *kvlangXvalueOwn(uint8_t *tmp, uint32_t tl, uint32_t *out_len) { - if (!tmp) { *out_len = 0; return NULL; } + if (!tmp) { + *out_len = 0; + return NULL; + } uint8_t *buf = malloc(tl); memcpy(buf, tmp, tl); free(tmp); @@ -64,16 +83,22 @@ static uint8_t *kvlangXvalueOwn(uint8_t *tmp, uint32_t tl, uint32_t *out_len) { } static uint8_t *kvlangXvalueEncodeTlv(const char *kind, const uint8_t *raw, - uint32_t raw_len, int32_t array_len, uint32_t *out_len) { - int32_t dims[1]; int32_t ndim = al_to_dims(kind, array_len, dims); - uint8_t *tmp = NULL; uint32_t tl = 0; - if (kvspaceTlvEncode(kind, raw, raw_len, dims, ndim, &tmp, &tl) != 0) { *out_len = 0; return NULL; } + uint32_t raw_len, int32_t array_len, uint32_t *out_len) { + int32_t dims[1]; + int32_t ndim = al_to_dims(kind, array_len, dims); + uint8_t *tmp = NULL; + uint32_t tl = 0; + if (kvspaceTlvEncode(kind, raw, raw_len, dims, ndim, &tmp, &tl) != 0) { + *out_len = 0; + return NULL; + } return kvlangXvalueOwn(tmp, tl, out_len); } int kvlangXvalueHead(const kvlangXvalue_t *v, kvspaceHead_t *h) { memset(h, 0, sizeof(*h)); - if (kvlangXvalueNone(v)) return -1; + if (kvlangXvalueNone(v)) + return -1; return kvlangXvalueDecodeHeadRaw(v->data, v->len, h); } @@ -82,46 +107,64 @@ const char *kvlangXvalueKind(const kvlangXvalue_t *v) { static __thread int idx = 0; char *b = buf[idx]; idx = (idx + 1) & 15; - if (kvlangXvalueNone(v)) { b[0] = 0; return b; } + if (kvlangXvalueNone(v)) { + b[0] = 0; + return b; + } kvspaceHead_t h; - if (kvlangXvalueHead(v, &h) < 0) { b[0] = 0; return b; } - kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + if (kvlangXvalueHead(v, &h) < 0) { + b[0] = 0; + return b; + } + kvlang_kindexpr_t kx; + kvlang_kindexpr_parse(h.kindexpr, &kx); int32_t kl = kx.kind_len; - if (kl > 32) kl = 32; + if (kl > 32) + kl = 32; memcpy(b, kx.kind, (size_t)kl); b[kl] = 0; return b; } bool kvlangXvalueKindIs(const kvlangXvalue_t *v, const char *kind) { - if (kvlangXvalueNone(v)) return kind[0] == 0; + if (kvlangXvalueNone(v)) + return kind[0] == 0; kvspaceHead_t h; - if (kvlangXvalueHead(v, &h) < 0) return false; - kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + if (kvlangXvalueHead(v, &h) < 0) + return false; + kvlang_kindexpr_t kx; + kvlang_kindexpr_parse(h.kindexpr, &kx); return (size_t)kx.kind_len == strlen(kind) && memcmp(kx.kind, kind, (size_t)kx.kind_len) == 0; } bool kvlangXvalueIsPtr(const kvlangXvalue_t *v) { - if (kvlangXvalueNone(v)) return false; + if (kvlangXvalueNone(v)) + return false; kvspaceHead_t h; - if (kvlangXvalueHead(v, &h) < 0) return false; - return h.xkind == KVSPACE_XKIND_PTR; + if (kvlangXvalueHead(v, &h) < 0) + return false; + return h.ref == KVSPACE_REF_PTR; } int32_t kvlangXvalueArrayLen(const kvlangXvalue_t *v) { - if (kvlangXvalueNone(v)) return 0; - kvspaceHead_t h; kvlangXvalueDecodeHeadRaw(v->data, v->len, &h); - kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); + if (kvlangXvalueNone(v)) + return 0; + kvspaceHead_t h; + kvlangXvalueDecodeHeadRaw(v->data, v->len, &h); + kvlang_kindexpr_t kx; + kvlang_kindexpr_parse(h.kindexpr, &kx); return kx.array_len; } const uint8_t *kvlangXvalueBody(const kvlangXvalue_t *v, const kvspaceHead_t *h, int32_t *out_len) { int32_t off = h->body_offset, len = h->body_len; if (off < 0 || len < 0 || off + len > (int32_t)v->len) { - if (out_len) *out_len = 0; + if (out_len) + *out_len = 0; return NULL; } - if (out_len) *out_len = len; + if (out_len) + *out_len = len; return v->data + off; } @@ -144,114 +187,192 @@ bool kvlangXvalueIsNumKind(const char *kind) { int32_t kvlangXvalueElemSize(const char *kind) { if (strcmp(kind, KVSPACE_KIND_INT8) == 0 || strcmp(kind, KVSPACE_KIND_UINT8) == 0 || strcmp(kind, KVSPACE_KIND_CHAR_UTF8) == 0 || strcmp(kind, KVSPACE_KIND_CHAR_ASCII) == 0 || - strcmp(kind, KVSPACE_KIND_BOOL) == 0) return 1; - if (strcmp(kind, KVSPACE_KIND_INT16) == 0 || strcmp(kind, KVSPACE_KIND_UINT16) == 0) return 2; + strcmp(kind, KVSPACE_KIND_BOOL) == 0) + return 1; + if (strcmp(kind, KVSPACE_KIND_INT16) == 0 || strcmp(kind, KVSPACE_KIND_UINT16) == 0) + return 2; if (strcmp(kind, KVSPACE_KIND_INT32) == 0 || strcmp(kind, KVSPACE_KIND_UINT32) == 0 || - strcmp(kind, KVSPACE_KIND_FLOAT32) == 0 || strcmp(kind, KVSPACE_KIND_CHAR) == 0) return 4; + strcmp(kind, KVSPACE_KIND_FLOAT32) == 0 || strcmp(kind, KVSPACE_KIND_CHAR) == 0) + return 4; if (strcmp(kind, KVSPACE_KIND_INT64) == 0 || strcmp(kind, KVSPACE_KIND_UINT64) == 0 || strcmp(kind, KVSPACE_KIND_FLOAT64) == 0 || strcmp(kind, KVSPACE_KIND_TIME) == 0 || - strcmp(kind, KVSPACE_KIND_DURATION) == 0) return 8; + strcmp(kind, KVSPACE_KIND_DURATION) == 0) + return 8; return 0; } static const uint8_t *v_body(const kvlangXvalue_t *v, kvspaceHead_t *h) { - if (kvlangXvalueDecodeHeadRaw(v->data, v->len, h) < 0) return NULL; + if (kvlangXvalueDecodeHeadRaw(v->data, v->len, h) < 0) + return NULL; return v->data + h->body_offset; } int64_t kvlangXvalueAsInt64(const kvlangXvalue_t *v) { - if (kvlangXvalueNone(v)) return 0; - kvspaceHead_t h; const uint8_t *b = v_body(v, &h); - if (!b) return 0; + if (kvlangXvalueNone(v)) + return 0; + kvspaceHead_t h; + const uint8_t *b = v_body(v, &h); + if (!b) + return 0; const char *k = kvlangXvalueKind(v); - if (strcmp(k, KVSPACE_KIND_BOOL) == 0) return b[0] != 0; - if (strcmp(k, KVSPACE_KIND_INT8) == 0) return (int8_t)b[0]; - if (strcmp(k, KVSPACE_KIND_INT16) == 0) return (int16_t)rd16(b); - if (strcmp(k, KVSPACE_KIND_INT32) == 0) return (int32_t)rd32(b); - if (strcmp(k, KVSPACE_KIND_INT64) == 0) return (int64_t)rd64(b); - if (strcmp(k, KVSPACE_KIND_UINT8) == 0) return b[0]; - if (strcmp(k, KVSPACE_KIND_UINT16) == 0) return rd16(b); - if (strcmp(k, KVSPACE_KIND_UINT32) == 0) return rd32(b); - if (strcmp(k, KVSPACE_KIND_UINT64) == 0) return (int64_t)rd64(b); - if (strcmp(k, KVSPACE_KIND_FLOAT32) == 0) { float f; uint32_t u = rd32(b); memcpy(&f, &u, 4); return (int64_t)f; } - if (strcmp(k, KVSPACE_KIND_FLOAT64) == 0) { double d; uint64_t u = rd64(b); memcpy(&d, &u, 8); return (int64_t)d; } - if (strcmp(k, KVSPACE_KIND_TIME) == 0 || strcmp(k, KVSPACE_KIND_DURATION) == 0) return (int64_t)rd64(b); + if (strcmp(k, KVSPACE_KIND_BOOL) == 0) + return b[0] != 0; + if (strcmp(k, KVSPACE_KIND_INT8) == 0) + return (int8_t)b[0]; + if (strcmp(k, KVSPACE_KIND_INT16) == 0) + return (int16_t)rd16(b); + if (strcmp(k, KVSPACE_KIND_INT32) == 0) + return (int32_t)rd32(b); + if (strcmp(k, KVSPACE_KIND_INT64) == 0) + return (int64_t)rd64(b); + if (strcmp(k, KVSPACE_KIND_UINT8) == 0) + return b[0]; + if (strcmp(k, KVSPACE_KIND_UINT16) == 0) + return rd16(b); + if (strcmp(k, KVSPACE_KIND_UINT32) == 0) + return rd32(b); + if (strcmp(k, KVSPACE_KIND_UINT64) == 0) + return (int64_t)rd64(b); + if (strcmp(k, KVSPACE_KIND_FLOAT32) == 0) { + float f; + uint32_t u = rd32(b); + memcpy(&f, &u, 4); + return (int64_t)f; + } + if (strcmp(k, KVSPACE_KIND_FLOAT64) == 0) { + double d; + uint64_t u = rd64(b); + memcpy(&d, &u, 8); + return (int64_t)d; + } + if (strcmp(k, KVSPACE_KIND_TIME) == 0 || strcmp(k, KVSPACE_KIND_DURATION) == 0) + return (int64_t)rd64(b); return 0; } double kvlangXvalueAsFloat64(const kvlangXvalue_t *v) { - if (kvlangXvalueNone(v)) return 0; - kvspaceHead_t h; const uint8_t *b = v_body(v, &h); - if (!b) return 0; + if (kvlangXvalueNone(v)) + return 0; + kvspaceHead_t h; + const uint8_t *b = v_body(v, &h); + if (!b) + return 0; const char *k = kvlangXvalueKind(v); - if (strcmp(k, KVSPACE_KIND_FLOAT32) == 0) { float f; uint32_t u = rd32(b); memcpy(&f, &u, 4); return f; } - if (strcmp(k, KVSPACE_KIND_FLOAT64) == 0) { double d; uint64_t u = rd64(b); memcpy(&d, &u, 8); return d; } + if (strcmp(k, KVSPACE_KIND_FLOAT32) == 0) { + float f; + uint32_t u = rd32(b); + memcpy(&f, &u, 4); + return f; + } + if (strcmp(k, KVSPACE_KIND_FLOAT64) == 0) { + double d; + uint64_t u = rd64(b); + memcpy(&d, &u, 8); + return d; + } return (double)kvlangXvalueAsInt64(v); } uint64_t kvlangXvalueAsUint64(const kvlangXvalue_t *v) { - if (kvlangXvalueNone(v)) return 0; - kvspaceHead_t h; const uint8_t *b = v_body(v, &h); - if (!b) return 0; + if (kvlangXvalueNone(v)) + return 0; + kvspaceHead_t h; + const uint8_t *b = v_body(v, &h); + if (!b) + return 0; const char *k = kvlangXvalueKind(v); - if (strcmp(k, KVSPACE_KIND_UINT8) == 0) return b[0]; - if (strcmp(k, KVSPACE_KIND_UINT16) == 0) return rd16(b); - if (strcmp(k, KVSPACE_KIND_UINT32) == 0) return rd32(b); - if (strcmp(k, KVSPACE_KIND_UINT64) == 0) return rd64(b); + if (strcmp(k, KVSPACE_KIND_UINT8) == 0) + return b[0]; + if (strcmp(k, KVSPACE_KIND_UINT16) == 0) + return rd16(b); + if (strcmp(k, KVSPACE_KIND_UINT32) == 0) + return rd32(b); + if (strcmp(k, KVSPACE_KIND_UINT64) == 0) + return rd64(b); return (uint64_t)kvlangXvalueAsInt64(v); } uint32_t kvlangXvalueChar32At(const kvlangXvalue_t *v, int32_t idx) { - kvspaceHead_t h; const uint8_t *b = v_body(v, &h); - if (!b) return 0; - kvlang_kindexpr_t kx; kvlang_kindexpr_parse(h.kindexpr, &kx); - if (idx < 0 || idx >= kx.array_len) return 0; + kvspaceHead_t h; + const uint8_t *b = v_body(v, &h); + if (!b) + return 0; + kvlang_kindexpr_t kx; + kvlang_kindexpr_parse(h.kindexpr, &kx); + if (idx < 0 || idx >= kx.array_len) + return 0; return rd32(b + idx * 4); } /* ── UTF-8 ↔ UTF-32 ────────────────────────────────────────────────── */ static void utf8_putc(kvlangStrbuf_t *b, uint32_t cp) { - if (cp < 0x80) kvlangStrbufPutc(b, (char)cp); - else if (cp < 0x800) { kvlangStrbufPutc(b, (char)(0xC0 | (cp >> 6))); kvlangStrbufPutc(b, (char)(0x80 | (cp & 0x3F))); } - else if (cp < 0x10000) { - kvlangStrbufPutc(b, (char)(0xE0 | (cp >> 12))); kvlangStrbufPutc(b, (char)(0x80 | ((cp >> 6) & 0x3F))); + if (cp < 0x80) + kvlangStrbufPutc(b, (char)cp); + else if (cp < 0x800) { + kvlangStrbufPutc(b, (char)(0xC0 | (cp >> 6))); + kvlangStrbufPutc(b, (char)(0x80 | (cp & 0x3F))); + } else if (cp < 0x10000) { + kvlangStrbufPutc(b, (char)(0xE0 | (cp >> 12))); + kvlangStrbufPutc(b, (char)(0x80 | ((cp >> 6) & 0x3F))); kvlangStrbufPutc(b, (char)(0x80 | (cp & 0x3F))); } else { - kvlangStrbufPutc(b, (char)(0xF0 | (cp >> 18))); kvlangStrbufPutc(b, (char)(0x80 | ((cp >> 12) & 0x3F))); - kvlangStrbufPutc(b, (char)(0x80 | ((cp >> 6) & 0x3F))); kvlangStrbufPutc(b, (char)(0x80 | (cp & 0x3F))); + kvlangStrbufPutc(b, (char)(0xF0 | (cp >> 18))); + kvlangStrbufPutc(b, (char)(0x80 | ((cp >> 12) & 0x3F))); + kvlangStrbufPutc(b, (char)(0x80 | ((cp >> 6) & 0x3F))); + kvlangStrbufPutc(b, (char)(0x80 | (cp & 0x3F))); } } static uint32_t utf8_next(const char *s, size_t *i, size_t len) { const unsigned char *p = (const unsigned char *)s; uint32_t cp = p[*i]; - if (cp < 0x80) { (*i)++; return cp; } + if (cp < 0x80) { + (*i)++; + return cp; + } int n = 0; - if ((cp & 0xE0) == 0xC0) { n = 1; cp &= 0x1F; } - else if ((cp & 0xF0) == 0xE0) { n = 2; cp &= 0x0F; } - else if ((cp & 0xF8) == 0xF0) { n = 3; cp &= 0x07; } - else { (*i)++; return 0xFFFD; } + if ((cp & 0xE0) == 0xC0) { + n = 1; + cp &= 0x1F; + } else if ((cp & 0xF0) == 0xE0) { + n = 2; + cp &= 0x0F; + } else if ((cp & 0xF8) == 0xF0) { + n = 3; + cp &= 0x07; + } else { + (*i)++; + return 0xFFFD; + } (*i)++; - for (int j = 0; j < n && *i < len; j++, (*i)++) cp = (cp << 6) | (p[*i] & 0x3F); + for (int j = 0; j < n && *i < len; j++, (*i)++) + cp = (cp << 6) | (p[*i] & 0x3F); return cp; } static char *utf32_to_utf8(const uint8_t *body, int32_t blen) { - kvlangStrbuf_t b; kvlangStrbufInit(&b); - for (int32_t i = 0; i + 4 <= blen; i += 4) utf8_putc(&b, rd32(body + i)); + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + for (int32_t i = 0; i + 4 <= blen; i += 4) + utf8_putc(&b, rd32(body + i)); return kvlangStrbufDetach(&b); } static char *strndup2(const uint8_t *p, int32_t n) { char *s = malloc((size_t)n + 1); - if (s) { memcpy(s, p, (size_t)n); s[n] = 0; } + if (s) { + memcpy(s, p, (size_t)n); + s[n] = 0; + } return s; } char *kvlangXvaluePtrTarget(const kvlangXvalue_t *v) { - kvspaceHead_t h; const uint8_t *b = v_body(v, &h); - if (!b) return strdup(""); + kvspaceHead_t h; + const uint8_t *b = v_body(v, &h); + if (!b) + return strdup(""); return strndup2(b, h.body_len); } @@ -261,48 +382,105 @@ static void append_num_int(kvlangStrbuf_t *b, int64_t n) { kvlangStrbufPrintf(b, static void append_num_uint(kvlangStrbuf_t *b, uint64_t n) { kvlangStrbufPrintf(b, "%llu", (unsigned long long)n); } char *kvlangXvalueValueString(const kvlangXvalue_t *v) { - if (kvlangXvalueNone(v)) return strdup(KVSPACE_KIND_NONE); - kvspaceHead_t h; const uint8_t *body = v_body(v, &h); - if (!body) return strdup(KVSPACE_KIND_NONE); + if (kvlangXvalueNone(v)) + return strdup(KVSPACE_KIND_NONE); + kvspaceHead_t h; + const uint8_t *body = v_body(v, &h); + if (!body) + return strdup(KVSPACE_KIND_NONE); int32_t blen = h.body_len; const char *k = kvlangXvalueKind(v); - if (h.xkind == KVSPACE_XKIND_PTR) { - kvlangStrbuf_t b; kvlangStrbufInit(&b); + if (h.ref == KVSPACE_REF_PTR) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); kvlangStrbufPutn(&b, "\xE2\x86\x92", 3); kvlangStrbufPutn(&b, (const char *)body, (size_t)blen); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_BOOL) == 0) return strdup(body[0] ? "true" : "false"); - if (strcmp(k, KVSPACE_KIND_INT8) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_int(&b, (int8_t)body[0]); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_INT16) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_int(&b, (int16_t)rd16(body)); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_INT32) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_int(&b, (int32_t)rd32(body)); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_INT64) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_int(&b, (int64_t)rd64(body)); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_UINT8) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_uint(&b, body[0]); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_UINT16) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_uint(&b, rd16(body)); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_UINT32) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_uint(&b, rd32(body)); return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_UINT64) == 0) { kvlangStrbuf_t b; kvlangStrbufInit(&b); append_num_uint(&b, rd64(body)); return kvlangStrbufDetach(&b); } + if (strcmp(k, KVSPACE_KIND_BOOL) == 0) + return strdup(body[0] ? "true" : "false"); + if (strcmp(k, KVSPACE_KIND_INT8) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_int(&b, (int8_t)body[0]); + return kvlangStrbufDetach(&b); + } + if (strcmp(k, KVSPACE_KIND_INT16) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_int(&b, (int16_t)rd16(body)); + return kvlangStrbufDetach(&b); + } + if (strcmp(k, KVSPACE_KIND_INT32) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_int(&b, (int32_t)rd32(body)); + return kvlangStrbufDetach(&b); + } + if (strcmp(k, KVSPACE_KIND_INT64) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_int(&b, (int64_t)rd64(body)); + return kvlangStrbufDetach(&b); + } + if (strcmp(k, KVSPACE_KIND_UINT8) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_uint(&b, body[0]); + return kvlangStrbufDetach(&b); + } + if (strcmp(k, KVSPACE_KIND_UINT16) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_uint(&b, rd16(body)); + return kvlangStrbufDetach(&b); + } + if (strcmp(k, KVSPACE_KIND_UINT32) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_uint(&b, rd32(body)); + return kvlangStrbufDetach(&b); + } + if (strcmp(k, KVSPACE_KIND_UINT64) == 0) { + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + append_num_uint(&b, rd64(body)); + return kvlangStrbufDetach(&b); + } if (strcmp(k, KVSPACE_KIND_FLOAT32) == 0 || strcmp(k, KVSPACE_KIND_FLOAT64) == 0) { - char tmp[64]; kvlangFormatFloat(tmp, sizeof tmp, kvlangXvalueAsFloat64(v)); return strdup(tmp); + char tmp[64]; + kvlangFormatFloat(tmp, sizeof tmp, kvlangXvalueAsFloat64(v)); + return strdup(tmp); } - if (strcmp(k, KVSPACE_KIND_CHAR_UTF8) == 0 || strcmp(k, KVSPACE_KIND_CHAR_ASCII) == 0) return strndup2(body, blen); - if (strcmp(k, KVSPACE_KIND_CHAR) == 0) return utf32_to_utf8(body, blen); - if (strcmp(k, KVSPACE_KIND_RWIR) == 0 || strcmp(k, KVSPACE_KIND_RWIR_OR_RWFUNC) == 0) return strndup2(body + (blen >= 4 ? 4 : 0), blen >= 4 ? blen - 4 : 0); + if (strcmp(k, KVSPACE_KIND_CHAR_UTF8) == 0 || strcmp(k, KVSPACE_KIND_CHAR_ASCII) == 0) + return strndup2(body, blen); + if (strcmp(k, KVSPACE_KIND_CHAR) == 0) + return utf32_to_utf8(body, blen); + if (strcmp(k, KVSPACE_KIND_RWIR) == 0 || strcmp(k, KVSPACE_KIND_RWIR_OR_RWFUNC) == 0) + return strndup2(body + (blen >= 4 ? 4 : 0), blen >= 4 ? blen - 4 : 0); if (strcmp(k, KVSPACE_KIND_RWFUNC) == 0) { - kvlangStrbuf_t b; kvlangStrbufInit(&b); + kvlangStrbuf_t b; + kvlangStrbufInit(&b); kvlangStrbufPrintf(&b, "r%d/w%d", (blen >= 2 ? rd16(body) : 0), (blen >= 4 ? rd16(body + 2) : 0)); return kvlangStrbufDetach(&b); } if (strcmp(k, KVSPACE_KIND_INDEX) == 0) { int n = blen >= 4 ? (int)rd32(body) : 0; - kvlangStrbuf_t b; kvlangStrbufInit(&b); kvlangStrbufPrintf(&b, "(%d)", n); return kvlangStrbufDetach(&b); + kvlangStrbuf_t b; + kvlangStrbufInit(&b); + kvlangStrbufPrintf(&b, "(%d)", n); + return kvlangStrbufDetach(&b); } - if (strcmp(k, KVSPACE_KIND_OBJ) == 0) return strdup(KVSPACE_KIND_OBJ); + if (strcmp(k, KVSPACE_KIND_OBJ) == 0) + return strdup(KVSPACE_KIND_OBJ); if (strcmp(k, KVSPACE_KIND_MAP) == 0) { - kvlangStrbuf_t b; kvlangStrbufInit(&b); + kvlangStrbuf_t b; + kvlangStrbufInit(&b); kvlangStrbufPuts(&b, "map["); for (int d = 0; d < h.ndim; d++) { - if (d) kvlangStrbufPutc(&b, ','); + if (d) + kvlangStrbufPutc(&b, ','); kvlangStrbufPrintf(&b, "%d", h.dims[d]); } kvlangStrbufPutc(&b, ']'); @@ -322,26 +500,38 @@ void kvlangXvalueNewTlv(kvlangXvalue_t *v, const char *kind, const uint8_t *raw, /* 显式 ndim/dims 构造(保留多维 shape,供 xv.shape/xv.set 用)。 */ void kvlangXvalueNewTlvDims(kvlangXvalue_t *v, const char *kind, const uint8_t *raw, uint32_t raw_len, const int32_t *dims, int32_t ndim) { - uint8_t *tmp = NULL; uint32_t tl = 0; + uint8_t *tmp = NULL; + uint32_t tl = 0; if (kvspaceTlvEncode(kind, raw, raw_len, dims, ndim, &tmp, &tl) != 0 || !tmp) { - v->data = NULL; v->len = 0; return; + v->data = NULL; + v->len = 0; + return; } uint8_t *buf = malloc(tl); memcpy(buf, tmp, tl); free(tmp); - v->data = buf; v->len = tl; + v->data = buf; + v->len = tl; } void kvlangXvalueNewInt64(kvlangXvalue_t *v, int64_t n) { uint8_t r[8]; - r[0] = n & 0xFF; r[1] = (n >> 8) & 0xFF; r[2] = (n >> 16) & 0xFF; r[3] = (n >> 24) & 0xFF; - r[4] = (n >> 32) & 0xFF; r[5] = (n >> 40) & 0xFF; r[6] = (n >> 48) & 0xFF; r[7] = (n >> 56) & 0xFF; + r[0] = n & 0xFF; + r[1] = (n >> 8) & 0xFF; + r[2] = (n >> 16) & 0xFF; + r[3] = (n >> 24) & 0xFF; + r[4] = (n >> 32) & 0xFF; + r[5] = (n >> 40) & 0xFF; + r[6] = (n >> 48) & 0xFF; + r[7] = (n >> 56) & 0xFF; kvlangXvalueNewTlv(v, KVSPACE_KIND_INT64, r, 8, 1); } void kvlangXvalueNewFloat64(kvlangXvalue_t *v, double f) { - uint64_t u; memcpy(&u, &f, 8); + uint64_t u; + memcpy(&u, &f, 8); uint8_t r[8]; - for (int i = 0; i < 8; i++) r[i] = (u >> (i * 8)) & 0xFF; + for (int i = 0; i < 8; i++) + r[i] = (u >> (i * 8)) & 0xFF; kvlangXvalueNewTlv(v, KVSPACE_KIND_FLOAT64, r, 8, 1); } void kvlangXvalueNewBool(kvlangXvalue_t *v, bool b) { @@ -358,11 +548,12 @@ void kvlangXvalueNewCharKind(kvlangXvalue_t *v, const char *kind, const char *s) } void kvlangXvalueNewCharUtf32(kvlangXvalue_t *v, const char *s) { size_t len = strlen(s); - kvlangStrbuf_t raw; kvlangStrbufInit(&raw); + kvlangStrbuf_t raw; + kvlangStrbufInit(&raw); size_t i = 0; while (i < len) { uint32_t cp = utf8_next(s, &i, len); - uint8_t le[4] = { cp & 0xFF, (cp >> 8) & 0xFF, (cp >> 16) & 0xFF, (cp >> 24) & 0xFF }; + uint8_t le[4] = {cp & 0xFF, (cp >> 8) & 0xFF, (cp >> 16) & 0xFF, (cp >> 24) & 0xFF}; kvlangStrbufPutn(&raw, (const char *)le, 4); } kvlangXvalueNewTlv(v, KVSPACE_KIND_CHAR, (const uint8_t *)raw.p, (uint32_t)raw.len, (int32_t)(raw.len / 4)); @@ -370,16 +561,23 @@ void kvlangXvalueNewCharUtf32(kvlangXvalue_t *v, const char *s) { } /* 指针:head kindexpr = "*" + target_kindexpr(目标完整 kindexpr),body = 目标 key。 */ void kvlangXvalueNewPtr(kvlangXvalue_t *v, const char *target_kindexpr, const char *target) { - uint8_t *tmp = NULL; uint32_t tl = 0, len = 0; - if (kvspaceNewPtr(target_kindexpr, target, &tmp, &tl) != 0) { v->data = NULL; v->len = 0; return; } + uint8_t *tmp = NULL; + uint32_t tl = 0, len = 0; + if (kvspaceNewPtr(target_kindexpr, target, &tmp, &tl) != 0) { + v->data = NULL; + v->len = 0; + return; + } v->data = kvlangXvalueOwn(tmp, tl, &len); v->len = len; } void kvlangXvalueNewRwir(kvlangXvalue_t *v, int32_t nr, int32_t nw, const char *sig) { size_t sl = strlen(sig); uint8_t *raw = malloc(4 + sl); - raw[0] = nr & 0xFF; raw[1] = (nr >> 8) & 0xFF; - raw[2] = nw & 0xFF; raw[3] = (nw >> 8) & 0xFF; + raw[0] = nr & 0xFF; + raw[1] = (nr >> 8) & 0xFF; + raw[2] = nw & 0xFF; + raw[3] = (nw >> 8) & 0xFF; memcpy(raw + 4, sig, sl); kvlangXvalueNewTlv(v, KVSPACE_KIND_DEF_RWIR, raw, (uint32_t)(4 + sl), 1); free(raw); @@ -388,16 +586,26 @@ void kvlangXvalueNewRwir(kvlangXvalue_t *v, int32_t nr, int32_t nw, const char * void kvlangFormatFloat(char *out, size_t cap, double v) { char s[64]; snprintf(s, sizeof s, "%.16g", v); - if (strtod(s, NULL) != v) snprintf(s, sizeof s, "%.17g", v); + if (strtod(s, NULL) != v) + snprintf(s, sizeof s, "%.17g", v); snprintf(out, cap, "%s", s); - if (strchr(out, 'e')) return; + if (strchr(out, 'e')) + return; char *dot = strchr(out, '.'); if (!dot) { size_t l = strlen(out); - if (l + 2 < cap) { out[l] = '.'; out[l + 1] = '0'; out[l + 2] = 0; } + if (l + 2 < cap) { + out[l] = '.'; + out[l + 1] = '0'; + out[l + 2] = 0; + } return; } char *p = out + strlen(out) - 1; - while (p > dot && *p == '0') *p-- = 0; - if (p == dot) { p[1] = '0'; p[2] = 0; } + while (p > dot && *p == '0') + *p-- = 0; + if (p == dot) { + p[1] = '0'; + p[2] = 0; + } }