Can not leave or re-enter the container when parsing the SENML-CBOR array
Opened this issue · 2 comments
Hello, I am dealing with a such SENML-CBOR array:
[{0: "/3/0/10", 2: 55}]
It has one item and 2 maps as you can see.
Also this aray may be bigger, for example:
[{0: "/3/0/10", 2: 55}, {0: "/3/0/12", 3: "ResetErrors"}, {0: "/3/0/13", 6: 2889055551}, {0: "/3/0/4", 3: "Reboot"}, {0: "/3/0/9", 2: 100}].
I am trying to run through this array once, check the every first map of every item of the array and then I need to get back to the begining of this array and parse it to the end.
But I have an issue with getting back to the array's begining/start.
Here is my code with yours library've been implemented:
err = cbor_parser_init(buffer, bufferLen, 0, &parser, &array);
if (err != CborNoError)
{
LOG_ARG("cbor_parser_init FAILED with error %d", err);
return -1;
}
CborType type = cbor_value_get_type(&array);
LOG_ARG("type = %x(%d)", type, type);
if (type == CborArrayType)
{
err = cbor_value_get_array_length(&array, &arrLen);
if (err != CborNoError)
{
LOG_ARG("cbor_value_get_array_length FAILED with error %d", err);
return -1;
}
LOG_ARG("array length = %d", arrLen);
if (arrLen <= 0) {
LOG("wrong array length FAILED");
return -1;
}
if (arrLen > 0)
{
sCount = prv_count_s_in_array(&array);
LOG_ARG("s quantity = %d", sCount);
LOG_ARG("array remaining = %d", array.remaining);
/// Here I need to get back to the array.start and parse it "once again"
}
/* prv_count_s_in_array brief*/
size_t prv_count_s_in_array(CborValue* array) {
CborValue map;
CborError err;
CborValue arrayStart;
int sCount = 0;
// Enter the CBOR array
err = cbor_value_enter_container(array, array);
if (err != CborNoError)
{
LOG_ARG("cbor_value_enter_container array FAILED with error %d", err);
return -1;
}
// Save the starting position of the array
cbor_value_get_next_byte(&arrayStart);
arrayStart.parser = array->parser;
// Iterate through each map in the array
while (!cbor_value_at_end(array))
{
LOG("CHECKPOINT 1 -------------------------------------------");
err = cbor_value_enter_container(array, &map); // Enter each map
if (err != CborNoError)
{
LOG_ARG("cbor_value_enter_container map FAILED with error %d", err);
return -1;
}
while (!cbor_value_at_end(&map))
{
LOG("CHECKPOINT 2 -------------------------------------------");
// Skip the key
err = cbor_value_advance(&map);
if (err != CborNoError) {
printf("Error advancing to value\n");
return -1;
}
// Get the value
CborType typeMap = cbor_value_get_type(&map);
if (typeMap == CborTextStringType)
{
// If the value is a text string, count the backslashes
// if (cbor_value_is_text_string(&map)) {
size_t len;
char *text;
cbor_value_dup_text_string(&map, &text, &len, NULL);
// Count *** in the string
int sCount = countS(text);
// Check if the count is equal to 3 (indicating a resource)
if (sCount == 2) {
sCount++;
}
}/// MAP_NAME
// Move to the next key-value pair
err = cbor_value_advance(&map);
if (err != CborNoError) {
LOG_ARG("cbor_value_advance map FAILED with error %d", err);
return -1;
}
}///!while not end map
LOG("CHECKPOINT 4 -------------------------------------------");
err = cbor_value_leave_container(array, &map); /// leave the map
if (err != CborNoError)
{
LOG_ARG("cbor_value_leave_container array FAILED with error %d", err);
return -1;
}
LOG("CHECKPOINT 5 -------------------------------------------");
LOG_ARG("array->remaining %d", array->remaining);
/// Move to the next map
if (array->remaining > 1){
err = cbor_value_advance(array);
if (err != CborNoError) {
LOG_ARG("cbor_value_advance array FAILED with error %d", err);
return -1;
}
}
}///!while not end of array
/// Here I have tried to leave the array-array-container or/and enter the array-array-container once more but FAILED
/// err = cbor_value_leave_container(array, array); /// leave the array
/// if (err != CborNoError)
/// {
/// LOG_ARG("cbor_value_leave_container array FAILED with error %d", err);
/// return -1;
/// }
LOG("CHECKPOINT 6 -------------------------------------------");
/// err = cbor_value_enter_container(array, array); /// re-enter the array
/// if (err != CborNoError)
/// {
/// LOG_ARG("cbor_value_leave_container array FAILED with error %d", err);
/// return -1;
/// }
// Reset the array pointer to the starting position
*array = arrayStart;
return resourceCount;
}
So, is the entering of the same container possible? Or, maybe, there is some other method to switch back the CborValue to the start of the cbor-buffer?
I guess that leave-container() may not work, cause there may be NO next array - we have only one array and leave_container seems to need the next value to switch to.
But, why the enter-container does not work? I have checked the array.remaining and it was 0 in the end of my function.
Now I am using a workaround - I am saving the starting point and re-setting it when I finish my checking function.
Also I want to admit that leave_container(array,map) works fine. So, question is about re-entering the array mainly.
Maybe there is something I have missed. Will be glad and grateful for any advice.
In any way, thanks for your library! Have a nice day, cheers!
[{0: "/3/0/10", 2: 55}]
It has one item and 2 maps as you can see.
That's one array with one map, and the map has two entries. That's different from:
[{0: "/3/0/10", 2: 55}, {0: "/3/0/12", 3: "ResetErrors"}, {0: "/3/0/13", 6: 2889055551}, {0: "/3/0/4", 3: "Reboot"}, {0: "/3/0/9", 2: 100}]
That's an array with multiple maps, each of which has two entries.
// Save the starting position of the array cbor_value_get_next_byte(&arrayStart); arrayStart.parser = array->parser; ... // Reset the array pointer to the starting position *array = arrayStart;
Don't do that. Just save the CborValue
object at that state. Those objects are copyable and, if you're just reading from a buffer, you can do it all over again.
LOG("CHECKPOINT 4 -------------------------------------------"); err = cbor_value_leave_container(array, &map); /// leave the map if (err != CborNoError) { LOG_ARG("cbor_value_leave_container array FAILED with error %d", err); return -1; } LOG("CHECKPOINT 5 -------------------------------------------"); LOG_ARG("array->remaining %d", array->remaining); /// Move to the next map if (array->remaining > 1){ err = cbor_value_advance(array); if (err != CborNoError) { LOG_ARG("cbor_value_advance array FAILED with error %d", err); return -1; } }
You shouldn't do that advance
. The cbor_value_leave_container
repositions the array
iterator to the next element. I think you can just delete the block starting from CHECKPOINT 5 to the end of the loop.