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 lwm2m_json_serialize(int size, lwm2m_data_t * tlvP, uint8_t ** bufferP) { int index; size_t head; uint8_t bufferJSON[PRV_JSON_BUFFER_SIZE]; memcpy(bufferJSON, JSON_HEADER, JSON_HEADER_SIZE); head = JSON_HEADER_SIZE; // HACK START if (tlvP->type == LWM2M_TYPE_OBJECT_INSTANCE) { if (size == 1) { size = tlvP->length; tlvP = (lwm2m_data_t *)tlvP->value; } else return 0; } // HACK END for (index = 0 ; index < size && head < PRV_JSON_BUFFER_SIZE ; index++) { int res; // TODO: handle non-text format switch (tlvP[index].type) { case LWM2M_TYPE_MULTIPLE_RESOURCE: { lwm2m_data_t * subTlvP; size_t i; subTlvP = (lwm2m_data_t *)tlvP[index].value; for (i = 0 ; i < tlvP[index].length ; i++) { res = lwm2m_snprintf((char *)bufferJSON + head, PRV_JSON_BUFFER_SIZE - head, JSON_INST_ITEM_TEMPLATE, tlvP[index].id, subTlvP[i].id); if (res <= 0 || res >= PRV_JSON_BUFFER_SIZE - head) return 0; head += res; res = prv_serializeValue(subTlvP + i, bufferJSON + head, PRV_JSON_BUFFER_SIZE -head); if (res < 0) return -1; head += res; } } break; case LWM2M_TYPE_RESOURCE: res = lwm2m_snprintf((char *)bufferJSON + head, PRV_JSON_BUFFER_SIZE - head, JSON_RES_ITEM_TEMPLATE, tlvP[index].id); if (res <= 0 || res >= PRV_JSON_BUFFER_SIZE - head) return 0; head += res; res = prv_serializeValue(tlvP + index, bufferJSON + head, PRV_JSON_BUFFER_SIZE -head); if (res < 0) return 0; head += res; break; case LWM2M_TYPE_OBJECT_INSTANCE: // TODO: support this. Hacked for now. break; case LWM2M_TYPE_RESOURCE_INSTANCE: default: return 0; break; } } if (head + JSON_FOOTER_SIZE - 1 > PRV_JSON_BUFFER_SIZE) return -1; memcpy(bufferJSON + head - 1, JSON_FOOTER, JSON_FOOTER_SIZE); head = head - 1 + JSON_FOOTER_SIZE; *bufferP = (uint8_t *)lwm2m_malloc(head); if (*bufferP == NULL) return 0; memcpy(*bufferP, bufferJSON, head); return (int)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; }