int json_serialize(lwm2m_uri_t * uriP, int size, lwm2m_data_t * tlvP, uint8_t ** bufferP) { int index; size_t head; uint8_t bufferJSON[PRV_JSON_BUFFER_SIZE]; uint8_t baseUriStr[URI_MAX_STRING_LEN]; int baseUriLen; uri_depth_t rootLevel; int num; lwm2m_data_t * targetP; LOG_ARG("size: %d", size); LOG_URI(uriP); if (size != 0 && tlvP == NULL) return -1; baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &rootLevel); if (baseUriLen < 0) return -1; num = prv_findAndCheckData(uriP, rootLevel, size, tlvP, &targetP); if (num < 0) return -1; while (num == 1 && (targetP->type == LWM2M_TYPE_OBJECT || targetP->type == LWM2M_TYPE_OBJECT_INSTANCE || targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)) { int res; res = utils_intToText(targetP->id, baseUriStr + baseUriLen, URI_MAX_STRING_LEN - baseUriLen); if (res <= 0) return 0; baseUriLen += res; if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0; num = targetP->value.asChildren.count; targetP = targetP->value.asChildren.array; baseUriStr[baseUriLen] = '/'; baseUriLen++; } if (baseUriLen > 0) { memcpy(bufferJSON, JSON_BN_HEADER_1, JSON_BN_HEADER_1_SIZE); head = JSON_BN_HEADER_1_SIZE; memcpy(bufferJSON + head, baseUriStr, baseUriLen); head += baseUriLen; memcpy(bufferJSON + head, JSON_BN_HEADER_2, JSON_BN_HEADER_2_SIZE); head += JSON_BN_HEADER_2_SIZE; } else { memcpy(bufferJSON, JSON_HEADER, JSON_HEADER_SIZE); head = JSON_HEADER_SIZE; } for (index = 0 ; index < num && head < PRV_JSON_BUFFER_SIZE ; index++) { int res; res = prv_serializeData(targetP + index, NULL, 0, bufferJSON + head, PRV_JSON_BUFFER_SIZE - head); if (res < 0) return res; head += res; } if (head + JSON_FOOTER_SIZE - 1 > PRV_JSON_BUFFER_SIZE) return 0; if (num > 0) head = head - 1; memcpy(bufferJSON + head, JSON_FOOTER, JSON_FOOTER_SIZE); head = head + JSON_FOOTER_SIZE; *bufferP = (uint8_t *)lwm2m_malloc(head); if (*bufferP == NULL) return -1; memcpy(*bufferP, bufferJSON, head); return head; }
static int prv_serializeData(const lwm2m_data_t * tlvP, const uint8_t * baseUriStr, size_t baseUriLen, uri_depth_t baseLevel, const uint8_t * parentUriStr, size_t parentUriLen, uri_depth_t level, bool *baseNameOutput, uint8_t * buffer, size_t bufferLen) { size_t head; int res; head = 0; /* Check to override passed in level */ switch (tlvP->type) { case LWM2M_TYPE_MULTIPLE_RESOURCE: level = URI_DEPTH_RESOURCE; break; case LWM2M_TYPE_OBJECT: level = URI_DEPTH_OBJECT; break; case LWM2M_TYPE_OBJECT_INSTANCE: level = URI_DEPTH_OBJECT_INSTANCE; break; default: break; } switch (tlvP->type) { case LWM2M_TYPE_MULTIPLE_RESOURCE: case LWM2M_TYPE_OBJECT: case LWM2M_TYPE_OBJECT_INSTANCE: { uint8_t uriStr[URI_MAX_STRING_LEN]; size_t uriLen; size_t index; if (parentUriLen > 0) { if (URI_MAX_STRING_LEN < parentUriLen) return -1; memcpy(uriStr, parentUriStr, parentUriLen); uriLen = parentUriLen; } else { uriLen = 0; } res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen); if (res <= 0) return -1; uriLen += res; uriStr[uriLen] = '/'; uriLen++; head = 0; for (index = 0 ; index < tlvP->value.asChildren.count; index++) { if (index != 0) { if (head + 1 > bufferLen) return 0; buffer[head++] = JSON_SEPARATOR; } res = prv_serializeData(tlvP->value.asChildren.array + index, baseUriStr, baseUriLen, baseLevel, uriStr, uriLen, level, baseNameOutput, buffer + head, bufferLen - head); if (res < 0) return -1; head += res; } } break; default: head = 0; if (bufferLen < 1) return -1; buffer[head++] = JSON_ITEM_BEGIN; if (!*baseNameOutput && baseUriLen > 0) { if (bufferLen - head < baseUriLen + JSON_BN_HEADER_SIZE + 2) return -1; memcpy(buffer + head, JSON_BN_HEADER, JSON_BN_HEADER_SIZE); head += JSON_BN_HEADER_SIZE; memcpy(buffer + head, baseUriStr, baseUriLen); head += baseUriLen; buffer[head++] = JSON_ITEM_STRING_END; buffer[head++] = JSON_SEPARATOR; *baseNameOutput = true; } /* TODO: support base time */ if (!baseUriLen || level > baseLevel) { if (bufferLen - head < JSON_ITEM_URI_SIZE) return -1; memcpy(buffer + head, JSON_ITEM_URI, JSON_ITEM_URI_SIZE); head += JSON_ITEM_URI_SIZE; if (parentUriLen > 0) { if (bufferLen - head < parentUriLen) return -1; memcpy(buffer + head, parentUriStr, parentUriLen); head += parentUriLen; } res = utils_intToText(tlvP->id, buffer + head, bufferLen - head); if (res <= 0) return -1; head += res; if (bufferLen - head < 2) return -1; buffer[head++] = JSON_ITEM_URI_END; if (tlvP->type != LWM2M_TYPE_UNDEFINED) { buffer[head++] = JSON_SEPARATOR; } } if (tlvP->type != LWM2M_TYPE_UNDEFINED) { res = prv_serializeValue(tlvP, buffer + head, bufferLen - head); if (res < 0) return -1; head += res; } /* TODO: support time */ if (bufferLen - head < 1) return -1; buffer[head++] = JSON_ITEM_END; break; } return (int)head; }
int prv_serializeData(lwm2m_data_t * tlvP, uint8_t * parentUriStr, size_t parentUriLen, uint8_t * buffer, size_t bufferLen) { int head; int res; head = 0; switch (tlvP->type) { case LWM2M_TYPE_OBJECT: case LWM2M_TYPE_OBJECT_INSTANCE: case LWM2M_TYPE_MULTIPLE_RESOURCE: { uint8_t uriStr[URI_MAX_STRING_LEN]; size_t uriLen; size_t index; if (parentUriLen > 0) { if (URI_MAX_STRING_LEN < parentUriLen) return -1; memcpy(uriStr, parentUriStr, parentUriLen); uriLen = parentUriLen; } else { uriLen = 0; } res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen); if (res <= 0) return -1; uriLen += res; uriStr[uriLen] = '/'; uriLen++; head = 0; for (index = 0 ; index < tlvP->value.asChildren.count; index++) { res = prv_serializeData(tlvP->value.asChildren.array + index, uriStr, uriLen, buffer + head, bufferLen - head); if (res < 0) return -1; head += res; } } break; default: if (bufferLen < JSON_RES_ITEM_URI_SIZE) return -1; memcpy(buffer, JSON_RES_ITEM_URI, JSON_RES_ITEM_URI_SIZE); head = JSON_RES_ITEM_URI_SIZE; if (parentUriLen > 0) { if (bufferLen - head < parentUriLen) return -1; memcpy(buffer + head, parentUriStr, parentUriLen); head += parentUriLen; } res = utils_intToText(tlvP->id, buffer + head, bufferLen - head); if (res <= 0) return -1; head += res; res = prv_serializeValue(tlvP, buffer + head, bufferLen - head); if (res < 0) return -1; head += res; break; } return head; }
int senml_json_serialize(const lwm2m_uri_t * uriP, int size, const lwm2m_data_t * tlvP, uint8_t ** bufferP) { int index; size_t head; uint8_t bufferJSON[PRV_JSON_BUFFER_SIZE]; uint8_t baseUriStr[URI_MAX_STRING_LEN]; int baseUriLen; uri_depth_t rootLevel; uri_depth_t baseLevel; int num; lwm2m_data_t * targetP; const uint8_t *parentUriStr = NULL; size_t parentUriLen = 0; LOG_ARG("size: %d", size); LOG_URI(uriP); if (size != 0 && tlvP == NULL) return -1; baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &baseLevel); if (baseUriLen < 0) return -1; if (baseUriLen > 1 && baseLevel != URI_DEPTH_RESOURCE && baseLevel != URI_DEPTH_RESOURCE_INSTANCE) { if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0; baseUriStr[baseUriLen++] = '/'; } num = json_findAndCheckData(uriP, json_decreaseLevel(baseLevel), size, tlvP, &targetP); if (num < 0) return -1; switch (tlvP->type) { case LWM2M_TYPE_OBJECT: rootLevel = URI_DEPTH_OBJECT; break; case LWM2M_TYPE_OBJECT_INSTANCE: rootLevel = URI_DEPTH_OBJECT_INSTANCE; break; case LWM2M_TYPE_MULTIPLE_RESOURCE: if (baseUriLen > 1 && baseUriStr[baseUriLen - 1] != '/') { if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0; baseUriStr[baseUriLen++] = '/'; } rootLevel = URI_DEPTH_RESOURCE_INSTANCE; break; default: if (baseLevel == URI_DEPTH_RESOURCE_INSTANCE) { rootLevel = URI_DEPTH_RESOURCE_INSTANCE; } else { rootLevel = URI_DEPTH_RESOURCE; } break; } if (!baseUriLen || baseUriStr[baseUriLen - 1] != '/') { parentUriStr = (const uint8_t *)"/"; parentUriLen = 1; } head = 0; bufferJSON[head++] = JSON_HEADER; bool baseNameOutput = false; for (index = 0 ; index < num && head < PRV_JSON_BUFFER_SIZE ; index++) { int res; if (index != 0) { if (head + 1 > PRV_JSON_BUFFER_SIZE) return 0; bufferJSON[head++] = JSON_SEPARATOR; } res = prv_serializeData(targetP + index, baseUriStr, baseUriLen, baseLevel, parentUriStr, parentUriLen, rootLevel, &baseNameOutput, bufferJSON + head, PRV_JSON_BUFFER_SIZE - head); if (res < 0) return res; head += res; } if (head + 1 > PRV_JSON_BUFFER_SIZE) return 0; bufferJSON[head++] = JSON_FOOTER; *bufferP = (uint8_t *)lwm2m_malloc(head); if (*bufferP == NULL) return -1; memcpy(*bufferP, bufferJSON, head); return head; }