Kaynağa Gözat

refactor: 避免未对齐访问

RyanCW 3 hafta önce
ebeveyn
işleme
bec534570a
3 değiştirilmiş dosya ile 77 ekleme ve 125 silme
  1. 72 31
      RyanJson/RyanJson.c
  2. 5 9
      RyanJson/RyanJson.h
  3. 0 85
      RyanJson/RyanJsonConfig.h

+ 72 - 31
RyanJson/RyanJson.c

@@ -168,13 +168,13 @@ static RyanJson_t RyanJsonCreateArrayAndKey(const char *key);
 static uint8_t *RyanJsonGetHiddePrt(RyanJson_t pJson)
 {
 	RyanJsonCheckAssert(NULL != pJson);
-	return *(uint8_t **)(RyanJsonGetPayloadPtr(pJson) + RyanJsonAlign);
+	return *(uint8_t **)(RyanJsonGetPayloadPtr(pJson) + sizeof(void *));
 }
 static void RyanJsonSetHiddePrt(RyanJson_t pJson, uint8_t *hiddePrt)
 {
 	RyanJsonCheckAssert(NULL != pJson);
 	RyanJsonCheckAssert(NULL != hiddePrt);
-	*(uint8_t **)(RyanJsonGetPayloadPtr(pJson) + RyanJsonAlign) = hiddePrt;
+	*(uint8_t **)(RyanJsonGetPayloadPtr(pJson) + sizeof(void *)) = hiddePrt;
 }
 
 /**
@@ -191,31 +191,22 @@ static uint8_t *RyanJsonGetHiddenPtrAt(RyanJson_t pJson, uint32_t index)
 }
 #pragma GCC diagnostic pop
 
-union RyanJsonUint32Bytes {
-	uint32_t value;
-	uint8_t buf[4];
-};
 static void RyanJsonSetLenKey(RyanJson_t pJson, uint32_t value)
 {
 	RyanJsonCheckAssert(NULL != pJson);
-	uint8_t *buf = RyanJsonGetHiddenPtrAt(pJson, 0);
-	uint8_t len = RyanJsonGetPayloadEncodeKeyLenByFlag(pJson);
-	RyanJsonCheckAssert(len <= 4);
 
-	union RyanJsonUint32Bytes tmpLenField = {.value = value};
-	for (uint8_t i = 0; i < len; i++) { buf[i] = tmpLenField.buf[i]; }
+	uint8_t *buf = (RyanJsonGetPayloadPtr(pJson) + sizeof(uint8_t));
+	RyanJsonMemcpy(buf, &value, 3);
 }
 
 static uint32_t RyanJsonGetLenKey(RyanJson_t pJson)
 {
 	RyanJsonCheckAssert(NULL != pJson);
-	uint8_t *buf = RyanJsonGetHiddenPtrAt(pJson, 0);
-	uint8_t len = RyanJsonGetPayloadEncodeKeyLenByFlag(pJson);
-	RyanJsonCheckAssert(len <= 4);
 
-	union RyanJsonUint32Bytes tmpLenField = {0};
-	for (uint8_t i = 0; i < len; i++) { tmpLenField.buf[i] = buf[i]; }
-	return tmpLenField.value;
+	uint8_t *buf = (RyanJsonGetPayloadPtr(pJson) + sizeof(uint8_t));
+	uint32_t value = 0;
+	RyanJsonMemcpy(&value, buf, 3);
+	return value;
 }
 
 /**
@@ -327,12 +318,21 @@ void *RyanJsonGetValue(RyanJson_t pJson)
 {
 	RyanJsonCheckReturnNull(NULL != pJson);
 
-	uint32_t len = RyanJsonAlign;
+	uint32_t len = 0;
 	if (RyanJsonIsKey(pJson) || RyanJsonIsString(pJson))
 	{
-		len += sizeof(void *);
+		len += sizeof(void *); // 对齐偏移
+		len += sizeof(void *); // key和Str的指针
 		// jsonLog(" keyLen: %d, keyLenField: %d, \r\n", RyanJsonGetLenKey(pJson), RyanJsonGetPayloadEncodeKeyLenByFlag(pJson));
 	}
+	else if (RyanJsonIsObject(pJson) || RyanJsonIsArray(pJson))
+	{
+		len += sizeof(void *); // 对齐偏移
+	}
+	else
+	{
+		len += sizeof(uint8_t); // 对齐偏移
+	}
 
 	return RyanJsonGetPayloadPtr(pJson) + len;
 }
@@ -340,7 +340,7 @@ void *RyanJsonGetValue(RyanJson_t pJson)
 char *RyanJsonGetKey(RyanJson_t pJson)
 {
 	RyanJsonCheckReturnNull(NULL != pJson);
-	return (char *)RyanJsonGetHiddenPtrAt(pJson, RyanJsonGetPayloadEncodeKeyLenByFlag(pJson));
+	return (char *)RyanJsonGetHiddenPtrAt(pJson, 0);
 }
 
 char *RyanJsonGetStringValue(RyanJson_t pJson)
@@ -348,17 +348,34 @@ char *RyanJsonGetStringValue(RyanJson_t pJson)
 	RyanJsonCheckReturnNull(NULL != pJson);
 
 	uint32_t len = 0;
-	if (RyanJsonIsKey(pJson)) { len = RyanJsonGetPayloadEncodeKeyLenByFlag(pJson) + RyanJsonGetLenKey(pJson) + 1U; }
+	if (RyanJsonIsKey(pJson)) { len = RyanJsonGetLenKey(pJson) + 1U; }
 
 	return (char *)RyanJsonGetHiddenPtrAt(pJson, len);
 }
 
+int32_t RyanJsonGetIntValue(RyanJson_t pJson)
+{
+	RyanJsonCheckCodeNoReturn(NULL != pJson, { return 0; });
+
+	int32_t intValue;
+	RyanJsonMemcpy(&intValue, RyanJsonGetValue(pJson), sizeof(intValue));
+	return intValue;
+}
+
+double RyanJsonGetDoubleValue(RyanJson_t pJson)
+{
+	RyanJsonCheckCodeNoReturn(NULL != pJson, { return 0; });
+
+	double doubleValue;
+	RyanJsonMemcpy(&doubleValue, RyanJsonGetValue(pJson), sizeof(doubleValue));
+	return doubleValue;
+}
+
 static RyanJsonBool_e RyanJsonChangeString(RyanJson_t pJson, RyanJsonBool_e isNew, const char *key, const char *strValue)
 {
 	RyanJsonCheckAssert(NULL != pJson);
 
 	uint32_t keyLen = 0;      // key的长度
-	uint8_t keyLenField = 0;  // 记录key长度需要几个字节
 	uint32_t strValueLen = 0; // stringValue的长度
 
 	uint32_t mallocSize = 0;
@@ -367,8 +384,7 @@ static RyanJsonBool_e RyanJsonChangeString(RyanJson_t pJson, RyanJsonBool_e isNe
 	if (NULL != key)
 	{
 		keyLen = RyanJsonStrlen(key);
-		keyLenField = RyanJsonCalcLenBytes(keyLen);
-		mallocSize += keyLen + keyLenField + 1 + 1;
+		mallocSize += keyLen + 1;
 
 #ifdef isEnableFuzzer
 		{
@@ -404,17 +420,15 @@ static RyanJsonBool_e RyanJsonChangeString(RyanJson_t pJson, RyanJsonBool_e isNe
 	if (NULL != key)
 	{
 		RyanJsonSetPayloadWhiteKeyByFlag(pJson, RyanJsonTrue);
-		RyanJsonSetPayloadEncodeKeyLenByFlag(pJson, keyLenField);
 		RyanJsonSetLenKey(pJson, keyLen);
 
-		jsonLog(" keyLen: %d, keyLenField: %d, \r\n", RyanJsonGetLenKey(pJson), RyanJsonGetPayloadEncodeKeyLenByFlag(pJson));
+		jsonLog("keyLen: %d, \r\n", RyanJsonGetLenKey(pJson));
 		if (0 != keyLen) { RyanJsonMemcpy(RyanJsonGetKey(pJson), key, keyLen); }
 		RyanJsonGetKey(pJson)[keyLen] = '\0';
 	}
 	else
 	{
 		RyanJsonSetPayloadWhiteKeyByFlag(pJson, RyanJsonFalse);
-		RyanJsonSetPayloadEncodeKeyLenByFlag(pJson, 0);
 	}
 
 	// 设置字符串值
@@ -434,7 +448,7 @@ static RyanJson_t RyanJsonNewNode(RyanJsonNodeInfo_t *info)
 	RyanJsonCheckAssert(NULL != info);
 
 	// 加1是flag的空间
-	uint32_t size = sizeof(struct RyanJsonNode) + RyanJsonAlign;
+	uint32_t size = sizeof(struct RyanJsonNode);
 
 	if (_checkType(info->type, RyanJsonTypeNumber))
 	{
@@ -446,7 +460,19 @@ static RyanJson_t RyanJsonNewNode(RyanJsonNodeInfo_t *info)
 	}
 	else if (_checkType(info->type, RyanJsonTypeArray) || _checkType(info->type, RyanJsonTypeObject)) { size += sizeof(RyanJson_t); }
 
-	if (NULL != info->key || _checkType(info->type, RyanJsonTypeString)) { size += sizeof(void *); }
+	if (NULL != info->key || _checkType(info->type, RyanJsonTypeString))
+	{
+		size += sizeof(void *); // 对齐偏移
+		size += sizeof(void *); // key和Str的指针
+	}
+	else if (_checkType(info->type, RyanJsonTypeArray) || _checkType(info->type, RyanJsonTypeObject))
+	{
+		size += sizeof(void *); // 对齐偏移
+	}
+	else
+	{
+		size += sizeof(uint8_t); // 对齐偏移
+	}
 
 	RyanJson_t pJson = (RyanJson_t)jsonMalloc((size_t)size);
 	if (NULL != pJson)
@@ -1070,6 +1096,7 @@ RyanJson_t RyanJsonParseOptions(const char *text, uint32_t size, RyanJsonBool_e
 	RyanJsonCheckReturnNull(RyanJsonTrue == parseBufSkipWhitespace(&parseBuf));
 
 	RyanJsonCheckReturnNull(RyanJsonTrue == RyanJsonParseValue(&parseBuf, NULL, &pJson));
+
 	// 检查解析后的文本后面是否有无意义的字符
 	RyanJsonCheckCode(RyanJsonTrue == RyanJsonParseCheckNullTerminator(&parseBuf, requireNullTerminator), {
 		RyanJsonDelete(pJson);
@@ -1848,6 +1875,20 @@ RyanJsonBool_e RyanJsonChangeStringValue(RyanJson_t pJson, const char *strValue)
 	return RyanJsonChangeString(pJson, RyanJsonFalse, RyanJsonIsKey(pJson) ? RyanJsonGetKey(pJson) : NULL, strValue);
 }
 
+RyanJsonBool_e RyanJsonChangeIntValue(RyanJson_t pJson, int32_t number)
+{
+	RyanJsonCheckReturnFalse(NULL != pJson);
+	RyanJsonMemcpy(RyanJsonGetValue(pJson), &number, sizeof(number));
+	return RyanJsonTrue;
+}
+
+RyanJsonBool_e RyanJsonChangeDoubleValue(RyanJson_t pJson, double number)
+{
+	RyanJsonCheckReturnFalse(NULL != pJson);
+	RyanJsonMemcpy(RyanJsonGetValue(pJson), &number, sizeof(number));
+	return RyanJsonTrue;
+}
+
 /**
  * @brief 创建一个 NULL 类型的json对象
  *
@@ -1885,7 +1926,7 @@ RyanJson_t RyanJsonCreateInt(const char *key, int32_t number)
 	RyanJson_t item = RyanJsonNewNode(&nodeInfo);
 	RyanJsonCheckReturnNull(NULL != item);
 
-	RyanJsonGetIntValue(item) = number;
+	RyanJsonChangeIntValue(item, number);
 	return item;
 }
 
@@ -1902,7 +1943,7 @@ RyanJson_t RyanJsonCreateDouble(const char *key, double number)
 	RyanJson_t item = RyanJsonNewNode(&nodeInfo);
 	RyanJsonCheckReturnNull(NULL != item);
 
-	RyanJsonGetDoubleValue(item) = number;
+	RyanJsonChangeDoubleValue(item, number);
 	return item;
 }
 

+ 5 - 9
RyanJson/RyanJson.h

@@ -153,10 +153,6 @@ typedef void *(*RyanJsonRealloc_t)(void *block, size_t size);
 #define RyanJsonGetPayloadWhiteKeyByFlag(pJson)        RyanJsonGetPayloadFlagField((pJson), 4, RyanJsonGetMask(1))
 #define RyanJsonSetPayloadWhiteKeyByFlag(pJson, value) RyanJsonSetPayloadFlagField((pJson), 4, RyanJsonGetMask(1), (value))
 
-// ! 使用超过8字节后一定要注意 RyanJsonSetPayloadFlagField 目前限制uint8_t类型
-// flag空间不够的时候可以把这个字段弃用,用redis的listpack方法将key和keyLen一起表示,内存占用也挺好,但是复杂度高,有空间就保持现在这样
-#define RyanJsonGetPayloadEncodeKeyLenByFlag(pJson)        ((uint8_t)RyanJsonGetPayloadFlagField((pJson), 5, RyanJsonGetMask(2)) + 1)
-#define RyanJsonSetPayloadEncodeKeyLenByFlag(pJson, value) RyanJsonSetPayloadFlagField((pJson), 5, RyanJsonGetMask(2), (value))
 extern RyanJsonBool_e RyanJsonInsert(RyanJson_t pJson, uint32_t index, RyanJson_t item);
 extern void *RyanJsonGetValue(RyanJson_t pJson);
 extern RyanJson_t RyanJsonCreateItem(const char *key, RyanJson_t item); // 需用户释放内存
@@ -247,9 +243,9 @@ extern RyanJsonBool_e RyanJsonIsDouble(RyanJson_t pJson);
  */
 extern char *RyanJsonGetKey(RyanJson_t pJson);
 extern char *RyanJsonGetStringValue(RyanJson_t pJson);
+extern int32_t RyanJsonGetIntValue(RyanJson_t pJson);
+extern double RyanJsonGetDoubleValue(RyanJson_t pJson);
 #define RyanJsonGetBoolValue(pJson)   RyanJsonGetPayloadBoolValueByFlag(pJson)
-#define RyanJsonGetIntValue(pJson)    (*(int32_t *)RyanJsonGetValue(pJson))
-#define RyanJsonGetDoubleValue(pJson) (*(double *)RyanJsonGetValue(pJson))
 #define RyanJsonGetArrayValue(pJson)  (*(RyanJson_t *)RyanJsonGetValue(pJson))
 #define RyanJsonGetObjectValue(pJson) (*(RyanJson_t *)RyanJsonGetValue(pJson))
 
@@ -284,9 +280,9 @@ extern RyanJsonBool_e RyanJsonAddItemToObject(RyanJson_t pJson, const char *key,
  */
 extern RyanJsonBool_e RyanJsonChangeKey(RyanJson_t pJson, const char *key);
 extern RyanJsonBool_e RyanJsonChangeStringValue(RyanJson_t pJson, const char *strValue);
-#define RyanJsonChangeBoolValue(pJson, boolean)  RyanJsonSetPayloadBoolValueByFlag(pJson, boolean)
-#define RyanJsonChangeIntValue(pJson, number)    (RyanJsonGetIntValue(pJson) = (number))
-#define RyanJsonChangeDoubleValue(pJson, number) (RyanJsonGetDoubleValue(pJson) = (number))
+extern RyanJsonBool_e RyanJsonChangeIntValue(RyanJson_t pJson, int32_t number);
+extern RyanJsonBool_e RyanJsonChangeDoubleValue(RyanJson_t pJson, double number);
+#define RyanJsonChangeBoolValue(pJson, boolean) RyanJsonSetPayloadBoolValueByFlag(pJson, boolean)
 
 // 这是change方法的补充,当需要修改value类型时,使用此函数
 // 请参考 changeJsonTest 示例,严格按照规则来使用

+ 0 - 85
RyanJson/RyanJsonConfig.h

@@ -36,15 +36,6 @@ extern "C" {
 // 是否启用assert
 // #define RyanJsonEnableAssert
 
-// 是否支持未对齐访问,未定义时会根据平台选择,
-// 一般不用管,如果你明白你的需求就自己定义
-// true 表示支持未对齐访问
-// false 表示不支持未对齐访问
-// UINT8_MAX 标识让RyanJson自动判断,但可能会漏掉支持对齐访问的平台
-#ifndef RyanJsonUnalignedAccessSupported
-#define RyanJsonUnalignedAccessSupported UINT8_MAX
-#endif
-
 // 限制解析数组/对象中嵌套的深度
 // RyanJson使用递归 序列化/反序列化 json
 // 请根据单片机资源合理设置以防止堆栈溢出。
@@ -70,82 +61,6 @@ extern "C" {
 #define RyanJsonAssert(EX) (void)(EX)
 #endif
 
-/**
- * @brief 判断是否支持未对齐访问
- *
- */
-#if UINT8_MAX == RyanJsonUnalignedAccessSupported
-#undef RyanJsonUnalignedAccessSupported
-
-// Cortex-M0/M0+/M1 属于 ARMv6-M
-#if defined(__ARM_ARCH_6M__)
-#define RyanJsonUnalignedAccessSupported false
-
-// Cortex-M3/M4/M7 属于 ARMv7-M/EM
-#elif defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
-#define RyanJsonUnalignedAccessSupported true
-
-// Cortex-M23/M33 属于 ARMv8-M
-#elif defined(__ARM_ARCH_8M_BASE__) || defined(__ARM_ARCH_8M_MAIN__)
-#define RyanJsonUnalignedAccessSupported true
-
-// Cortex-A/R 属于 ARMv7-A/R
-#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)
-#define RyanJsonUnalignedAccessSupported true
-
-// ARM9/ARM11 等老核
-#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__)
-#define RyanJsonUnalignedAccessSupported false
-
-// ARMv8-A / ARM64
-#elif defined(__aarch64__) || defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_9__)
-#define RyanJsonUnalignedAccessSupported true
-
-// RISC-V MCU 默认不支持未对齐访问
-#elif defined(__riscv)
-#define RyanJsonUnalignedAccessSupported false
-
-// x86 / x86-64
-#elif defined(__i386__) || defined(__x86_64__)
-#define RyanJsonUnalignedAccessSupported true
-
-// MIPS
-#elif defined(__mips__)
-#define RyanJsonUnalignedAccessSupported false
-
-// PowerPC
-#elif defined(__powerpc__) || defined(__ppc__)
-#define RyanJsonUnalignedAccessSupported false
-
-// SPARC
-#elif defined(__sparc__)
-#define RyanJsonUnalignedAccessSupported false
-
-// SuperH
-#elif defined(__sh__)
-#define RyanJsonUnalignedAccessSupported false
-
-// Alpha
-#elif defined(__alpha__)
-#define RyanJsonUnalignedAccessSupported true
-
-// Itanium
-#elif defined(__ia64__)
-#define RyanJsonUnalignedAccessSupported false
-
-#else
-// 默认认为不支持未对齐访问
-#define RyanJsonUnalignedAccessSupported false
-#endif
-
-#endif // UINT8_MAX == RyanJsonUnalignedAccessSupported
-
-#if true != RyanJsonUnalignedAccessSupported
-#define RyanJsonAlign sizeof(void *)
-#else
-#define RyanJsonAlign sizeof(uint8_t)
-#endif
-
 #ifdef __cplusplus
 }
 #endif