#include "proto.h" #include const char *proto_locate(const char *json, const char *key) { char pat[24]; int klen = (int)strlen(key); const char *p = json; if (klen <= 0 || klen + 3 > (int)sizeof(pat)) return 0; pat[0] = '"'; memcpy(pat + 1, key, klen); pat[klen + 1] = '"'; pat[klen + 2] = '\0'; while ((p = strstr(p, pat)) != 0) { const char *q = p + klen + 2; while (*q == ' ' || *q == '\t') q++; if (*q == ':') { q++; while (*q == ' ' || *q == '\t') q++; return q; } /* 命中的是字符串值里的子串而非键名,继续向后找 */ p += 2; } return 0; } /* 提取 key 的值区域到 buf(带花括号深度跟踪,嵌套对象整体取出)。 * 成功返回 1,失败返回 0。 */ static int proto_value_region(const char *json, const char *key, char *buf, int cap) { const char *p = proto_locate(json, key); int i = 0; int depth = 0; if (!p) return 0; while (p[i] && i < cap - 1) { char c = p[i]; if (c == '{') { depth++; } else if (c == '}') { if (depth == 0) break; /* 不属于本值的右括号 */ depth--; if (depth == 0) { i++; break; } /* 嵌套对象结束 */ } else if (c == ',' && depth == 0) { break; /* 顶层下一个字段 */ } buf[i] = c; i++; } buf[i] = '\0'; return 1; } int proto_get_bool(const char *json, const char *key, int *val) { char region[96]; char *q; int len; if (!proto_value_region(json, key, region, sizeof(region))) return 0; len = (int)strlen(region); /* 在值区域内找最先出现的 true/false 令牌(排除键名里的子串) */ for (q = region; q < region + len; q++) { if (q + 4 <= region + len && strncmp(q, "true", 4) == 0 && (q == region || q[-1] != '"')) { *val = 1; return 1; } if (q + 5 <= region + len && strncmp(q, "false", 5) == 0 && (q == region || q[-1] != '"')) { *val = 0; return 1; } } /* 兼容 0/1 */ if (region[0] == '0' || region[0] == '1') { *val = region[0] - '0'; return 1; } return 0; } int proto_get_u32(const char *json, const char *key, uint32_t *val) { const char *p = proto_locate(json, key); uint32_t v = 0; if (!p || *p < '0' || *p > '9') return 0; while (*p >= '0' && *p <= '9') { v = v * 10 + (uint32_t)(*p - '0'); p++; } *val = v; return 1; } int proto_get_hex16(const char *json, const char *key, uint16_t *val) { const char *p = proto_locate(json, key); uint16_t v = 0; int n = 0; if (!p) return 0; if (*p == '"') p++; while (n < 4) { char c = *p; uint8_t d; if (c >= '0' && c <= '9') d = (uint8_t)(c - '0'); else if (c >= 'a' && c <= 'f') d = (uint8_t)(c - 'a' + 10); else if (c >= 'A' && c <= 'F') d = (uint8_t)(c - 'A' + 10); else break; v = (uint16_t)((v << 4) | d); p++; n++; } if (n == 0) return 0; *val = v; return 1; } int proto_get_str(const char *json, const char *key, char *out, int cap) { const char *p = proto_locate(json, key); int i = 0; if (!p || *p != '"' || cap <= 0) return 0; p++; while (p[i] && p[i] != '"' && i < cap - 1) { out[i] = p[i]; i++; } out[i] = '\0'; return (i > 0) ? 1 : 0; } int proto_get_id(const char *json, char *out, int cap) { const char *p = proto_locate(json, "id"); int i = 0; if (!p || cap <= 0) return 0; if (*p == '"') { p++; while (i < cap - 1 && ((p[i] >= '0' && p[i] <= '9') || (p[i] >= 'a' && p[i] <= 'z') || (p[i] >= 'A' && p[i] <= 'Z'))) { out[i] = p[i]; i++; } } else { while (i < cap - 1 && p[i] >= '0' && p[i] <= '9') { out[i] = p[i]; i++; } } out[i] = '\0'; return (i > 0) ? 1 : 0; } int proto_get_kg100(const char *json, const char *key, uint16_t *val) { char region[64]; const char *p; const char *vp; uint16_t v = 0; if (!proto_value_region(json, key, region, sizeof(region))) return 0; /* 嵌套对象时取 "value" 字段,否则直接用区域本身 */ vp = proto_locate(region, "value"); p = vp ? vp : region; /* 跳过空白、引号、冒号 */ while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n' || *p == '"' || *p == ':') p++; if (*p < '0' || *p > '9') return 0; while (*p >= '0' && *p <= '9') { v = (uint16_t)(v * 10 + (*p - '0')); p++; } if (*p == '.') { p++; if (*p >= '0' && *p <= '9') { v = (uint16_t)(v * 10 + (*p - '0')); } else { v = (uint16_t)(v * 10); /* 整数补一位小数 */ } /* 忽略第二位小数 */ } else { v = (uint16_t)(v * 10); /* 整数转 0.1KG */ } *val = v; return 1; }